Pohled pod kapotu JVM – složené datové typy a programová smyčka typu for-each v Python VM

Pavel Tišnovský 29. 7. 2014

V dnešní části seriálu o programovacím jazyku Java i o virtuálním stroji Javy si ukážeme, jakým způsobem se překládají programové smyčky typu „for-each“ v Pythonu. Jedná se tedy o doplnění předchozích dvou částí, v nichž jsme se zabývali stejnou problematikou, ovšem z pohledu JVM a Lua VM.

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()sum()

11. Repositář se zdrojovými kódy všech tří dnešních demonstračních příkladů

12. Odkazy na Internetu

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/dow­nload/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íčhodnota.

Zejména instrukce GET_ITERFOR_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()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_SEQUENCEJUMP_ABSOLUTE:

widgety

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.or­g/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

  1. Python Byte Code Instructions
    https://docs.python.org/re­lease/2.5.2/lib/bytecodes­.html
  2. For-each Loop in Java
    http://www.leepoint.net/notes-java/flow/loops/foreach.html
  3. Programming in Lua (first edition)
    http://www.lua.org/pil/contents.html
  4. Programming in Lua: Numeric for
    http://www.lua.org/pil/4.3.4.html
  5. Programming in Lua: break and return
    http://www.lua.org/pil/4.4.html
  6. Programming in Lua: Tables
    http://www.lua.org/pil/2.5.html
  7. Programming in Lua: Table Constructors
    http://www.lua.org/pil/3.6.html
  8. Programovací jazyk Lua
    http://palmknihy.cz/web/kni­ha/programovaci-jazyk-lua-12651.htm
  9. Lua: Tables Tutorial
    http://lua-users.org/wiki/TablesTutorial
  10. Python 2.x: funkce range()
    https://docs.python.org/2/li­brary/functions.html#range
  11. Python 2.x: typ iterátor
    https://docs.python.org/2/li­brary/stdtypes.html#itera­tor-types
  12. Lua: Control Structure Tutorial
    http://lua-users.org/wiki/ControlStruc­tureTutorial
  13. Lua Types Tutorial
    http://lua-users.org/wiki/LuaTypesTutorial
  14. Goto Statement in Lua
    http://lua-users.org/wiki/GotoStatement
  15. Python break, continue and pass Statements
    http://www.tutorialspoint­.com/python/python_loop_con­trol.htm
  16. For Loop (Wikipedia)
    http://en.wikipedia.org/wiki/For_loop
  17. Heinz Rutishauser
    http://en.wikipedia.org/wi­ki/Heinz_Rutishauser
  18. Parrot
    http://www.parrot.org/
  19. Parrot languages
    http://www.parrot.org/languages
  20. Parrot Primer
    http://docs.parrot.org/pa­rrot/latest/html/docs/intro­.pod.html
  21. Parrot Opcodes
    http://docs.parrot.org/pa­rrot/latest/html/ops.html
  22. Parrot VM
    http://en.wikibooks.org/wi­ki/Parrot_Virtual_Machine
  23. Parrot Assembly Language
    http://www.perl6.org/archi­ve/pdd/pdd06_pasm.html
  24. Parrot Reference: Chapter 11 – Perl 6 and Parrot Essentials
    http://oreilly.com/perl/excerpts/perl-6-and-parrot-essentials/parrot-reference.html
  25. Python Bytecode: Fun With Dis
    http://akaptur.github.io/blog/2013/08/14/pyt­hon-bytecode-fun-with-dis/
  26. Python's Innards: Hello, ceval.c!
    http://tech.blog.aknin.na­me/category/my-projects/pythons-innards/
  27. Byterun
    https://github.com/nedbat/byterun
  28. Python Byte Code Instructions
    http://document.ihg.uni-duisburg.de/Documentation/Pyt­hon/lib/node56.html
  29. Python Byte Code Instructions
    https://docs.python.org/3­.2/library/dis.html#python-bytecode-instructions
  30. Lua 5.2 sources
    http://www.lua.org/source/5.2/
  31. Lua 5.2 sources – lopcodes.h
    http://www.lua.org/source/5­.2/lopcodes.h.html
  32. Lua 5.2 sources – lopcodes.c
    http://www.lua.org/source/5­.2/lopcodes.c.html
  33. dis – Python module
    https://docs.python.org/2/li­brary/dis.html
  34. Comparison of Python virtual machines
    http://polishlinux.org/ap­ps/cli/comparison-of-python-virtual-machines/
  35. O-code
    http://en.wikipedia.org/wiki/O-code_machine
  36. Java quick guide: JVM Instruction Set (tabulka všech instrukcí JVM)
    http://www.mobilefish.com/tu­torials/java/java_quickgu­ide_jvm_instruction_set.html
  37. The JVM Instruction Set
    http://mpdeboer.home.xs4a­ll.nl/scriptie/node14.html
  38. GC safe-point (or safepoint) and safe-region
    http://xiao-feng.blogspot.cz/2008/01/gc-safe-point-and-safe-region.html
  39. Safepoints in HotSpot JVM
    http://blog.ragozin.info/2012/10/sa­fepoints-in-hotspot-jvm.html
  40. Java theory and practice: Synchronization optimizations in Mustang
    http://www.ibm.com/develo­perworks/java/library/j-jtp10185/
  41. How to build hsdis
    http://hg.openjdk.java.net/jdk7/hot­spot/hotspot/file/tip/src/sha­re/tools/hsdis/README
  42. Java SE 6 Performance White Paper
    http://www.oracle.com/technet­work/java/6-performance-137236.html
  43. Lukas Stadler's Blog
    http://classparser.blogspot­.cz/2010/03/hsdis-i386dll.html
  44. How to build hsdis-amd64.dll and hsdis-i386.dll on Windows
    http://dropzone.nfshost.com/hsdis.htm
  45. PrintAssembly
    https://wikis.oracle.com/dis­play/HotSpotInternals/Prin­tAssembly
  46. The Java Virtual Machine Specification: 3.14. Synchronization
    http://docs.oracle.com/ja­vase/specs/jvms/se7/html/jvms-3.html#jvms-3.14
  47. The Java Virtual Machine Specification: 8.3.1.4. volatile Fields
    http://docs.oracle.com/ja­vase/specs/jls/se7/html/jls-8.html#jls-8.3.1.4
  48. The Java Virtual Machine Specification: 17.4. Memory Model
    http://docs.oracle.com/ja­vase/specs/jls/se7/html/jls-17.html#jls-17.4
  49. The Java Virtual Machine Specification: 17.7. Non-atomic Treatment of double and long
    http://docs.oracle.com/ja­vase/specs/jls/se7/html/jls-17.html#jls-17.7
  50. Open Source ByteCode Libraries in Java
    http://java-source.net/open-source/bytecode-libraries
  51. ASM Home page
    http://asm.ow2.org/
  52. Seznam nástrojů využívajících projekt ASM
    http://asm.ow2.org/users.html
  53. ObjectWeb ASM (Wikipedia)
    http://en.wikipedia.org/wi­ki/ObjectWeb_ASM
  54. Java Bytecode BCEL vs ASM
    http://james.onegoodcooki­e.com/2005/10/26/java-bytecode-bcel-vs-asm/
  55. BCEL Home page
    http://commons.apache.org/bcel/
  56. Byte Code Engineering Library (před verzí 5.0)
    http://bcel.sourceforge.net/
  57. Byte Code Engineering Library (verze >= 5.0)
    http://commons.apache.org/pro­per/commons-bcel/
  58. BCEL Manual
    http://commons.apache.org/bcel/ma­nual.html
  59. Byte Code Engineering Library (Wikipedia)
    http://en.wikipedia.org/wiki/BCEL
  60. BCEL Tutorial
    http://www.smfsupport.com/sup­port/java/bcel-tutorial!/
  61. Bytecode Engineering
    http://book.chinaunix.net/spe­cial/ebook/Core_Java2_Volu­me2AF/0131118269/ch13lev1sec6­.html
  62. Bytecode Outline plugin for Eclipse (screenshoty + info)
    http://asm.ow2.org/eclipse/index.html
  63. Javassist
    http://www.jboss.org/javassist/
  64. Byteman
    http://www.jboss.org/byteman
  65. Java programming dynamics, Part 7: Bytecode engineering with BCEL
    http://www.ibm.com/develo­perworks/java/library/j-dyn0414/
  66. The JavaTM Virtual Machine Specification, Second Edition
    http://java.sun.com/docs/bo­oks/jvms/second_edition/html/VMSpec­TOC.doc.html
  67. The class File Format
    http://java.sun.com/docs/bo­oks/jvms/second_edition/html/Clas­sFile.doc.html
  68. javap – The Java Class File Disassembler
    http://docs.oracle.com/ja­vase/1.4.2/docs/tooldocs/win­dows/javap.html
  69. javap-java-1.6.0-openjdk(1) – Linux man page
    http://linux.die.net/man/1/javap-java-1.6.0-openjdk
  70. Using javap
    http://www.idevelopment.in­fo/data/Programming/java/mis­cellaneous_java/Using_javap­.html
  71. Examine class files with the javap command
    http://www.techrepublic.com/ar­ticle/examine-class-files-with-the-javap-command/5815354
  72. aspectj (Eclipse)
    http://www.eclipse.org/aspectj/
  73. Aspect-oriented programming (Wikipedia)
    http://en.wikipedia.org/wi­ki/Aspect_oriented_program­ming
  74. AspectJ (Wikipedia)
    http://en.wikipedia.org/wiki/AspectJ
  75. EMMA: a free Java code coverage tool
    http://emma.sourceforge.net/
  76. Cobertura
    http://cobertura.sourceforge.net/
  77. jclasslib bytecode viewer
    http://www.ej-technologies.com/products/jclas­slib/overview.html
Našli jste v článku chybu?
120na80.cz: Poslední možnost změnit zdravotní pojišťovnu

Poslední možnost změnit zdravotní pojišťovnu

DigiZone.cz: Na jaká videa se vlastně díváme

Na jaká videa se vlastně díváme

Podnikatel.cz: EET a účetní programy. Vše hotovo?

EET a účetní programy. Vše hotovo?

DigiZone.cz: Banaxi: videa kdekoli na světě

Banaxi: videa kdekoli na světě

Vitalia.cz: 5 nemocí, se kterými pomáhá urologie

5 nemocí, se kterými pomáhá urologie

Vitalia.cz: 5 chyb, které děláme při skladování potravin

5 chyb, které děláme při skladování potravin

DigiZone.cz: Wimbledon na Nova Sport až do 2019

Wimbledon na Nova Sport až do 2019

Podnikatel.cz: Udělali jsme velkou chybu, napsal Čupr

Udělali jsme velkou chybu, napsal Čupr

Vitalia.cz: Jsou vegani a vyrábějí nemléko

Jsou vegani a vyrábějí nemléko

Lupa.cz: Cimrman má hry na YouTube i vlastní doodle

Cimrman má hry na YouTube i vlastní doodle

DigiZone.cz: Digi Slovakia zařazuje stanice SPI

Digi Slovakia zařazuje stanice SPI

DigiZone.cz: Rapl: seriál, který vás smíří s ČT

Rapl: seriál, který vás smíří s ČT

DigiZone.cz: Technisat připravuje trojici DAB

Technisat připravuje trojici DAB

Root.cz: Hořící telefon Samsung Note 7 zapálil auto

Hořící telefon Samsung Note 7 zapálil auto

Lupa.cz: Jak se prodává firma za miliardu?

Jak se prodává firma za miliardu?

Lupa.cz: Proč jsou firemní počítače pomalé?

Proč jsou firemní počítače pomalé?

Lupa.cz: Další Češi si nechali vložit do těla čip

Další Češi si nechali vložit do těla čip

DigiZone.cz: Světový pohár v přímém přenosu na ČT

Světový pohár v přímém přenosu na ČT

Podnikatel.cz: ČSSZ posílá přehled o důchodovém kontě

ČSSZ posílá přehled o důchodovém kontě

Vitalia.cz: Tahák, jak vyzrát nad zápachem z úst

Tahák, jak vyzrát nad zápachem z úst