Analýza a transformace kódu v Javě s knihovnou Spoon (2)

6. 10. 2016
Doba čtení: 16 minut

Sdílet

Ve druhém článku o knihovně Spoon, kterou lze použít pro analýzu či transformace kódu v Javě, dokončíme téma „procesorů“, jež mohou sloužit k relativně jednoduchým analýzám kódu.

Obsah

1. Analýza a transformace kódu psaného v Javě s využitím knihovny Spoon (2)

2. Třídy použité pro otestování činnosti procesorů

3. První procesor vypisující základní informace o nalezených konstruktorech

4. Překlad a použití prvního procesoru

5. Druhý procesor vypisující počet parametrů konstruktoru a počet příkazů v jeho těle

6. Otestování druhého procesoru

7. Výpis jednotlivých příkazů uvnitř těla konstruktorů a modifikátorů konstruktorů

8. Otestování třetího procesoru

9. Procesor pro detekci všech programových smyček

10. Otestování čtvrtého procesoru

11. Procesor pro zpracování informací o programových smyčkách typu while

12. Otestování pátého procesoru

13. Použité třídy a rozhraní knihovny Spoon

14. Odkazy na Internetu

1. Analýza a transformace kódu psaného v Javě s využitím knihovny Spoon (2)

V úvodním článku pojednávajícím o knihovně Spoon jsme se ve stručnosti seznámili s tím, jakým způsobem se v této knihovně reprezentují zdrojové kódy Javy s využitím abstraktního syntaktického stromu (AST). Taktéž jsme si ukázali některé základní možnosti nabízené takzvanými „procesory“, které je možné v případě potřeby použít pro relativně jednoduše zapsané (implementované) analyzátory kódů. Dnes toto téma dokončíme, protože si ukážeme několik dalších procesorů. Tvorba procesorů však samozřejmě nebude pouze samoúčelná, protože se při jejich vyváření seznámíme s některými dalšími vlastnostmi AST, tj. s typy objektů, které jsou do AST ukládány i se samotným způsobem ukládání (konstruktory, metody, programové smyčky, jednotlivé výrazy apod.)

2. Třídy použité pro otestování činnosti procesorů

Podobně jako tomu bylo minule, i v dnešním článku budou jednotlivé procesory testovány s využitím několika velmi jednoduchých tříd, které jsou ve stručnosti popsány v následujících podkapitolách:

EmptyClass

Zde je popis snadný – jedná se o prázdnou veřejnou třídu s implicitně vytvořeným konstruktorem. Ten sice není ve zdrojovém kódu viditelný, ale v AST ho najdeme (což odpovídá JLS):

public class EmptyClass {
}

ManyConstructors

Druhá třída obsahuje několik konstruktorů, které se od sebe odlišují počtem a typem parametrů, existencí či neexistencí těla konstruktoru a taktéž specifikovanou viditelností (private, protected, public, výchozí):

public class ManyConstructors {
 
    ManyConstructors() {
    }
 
    ManyConstructors(int x) {
    }
 
    ManyConstructors(int x, int y) {
    }
 
    ManyConstructors(String str) {
    }
 
    ManyConstructors(String... strs) {
    }
 
    ManyConstructors(float x) {
        System.out.println(x);
    }
 
    ManyConstructors(float x, float y) {
        System.out.println(x);
        System.out.println(y);
    }
 
    private ManyConstructors(double a) {
    }
 
    protected ManyConstructors(double a, double b) {
    }
 
    public ManyConstructors(double a, double b, double c) {
    }
}

WhileLoop1

Ve třetí testovací třídě nalezneme statickou metodu main() obsahující programovou smyčku typu while:

class WhileLoop1 {
    public static void main(String[] args) throws Exception {
        int i = 1;
 
        while (i <= 10) {
            System.out.println(i);
            i++;
        }
    }
}

Poznámka: deklarace throws Exception si prozatím nemusíme všímat, bude využita v dalších příkladech.

Loops

Poslední třída obsahuje trojici počítaných programových smyček. Nalezneme zde smyčku typu while, do-while i počítanou smyčku typu for:

class Loops {
    public static void main(String[] args) throws Exception {
        int i = 1;
 
        do {
            System.out.println(i);
            i++;
        } while (i<=10);
 
        i=1;
        while (i <= 10) {
            System.out.println(i);
            i++;
        }
 
        for (i=0; i<10; i++) {
            System.out.println(i);
        }
    }
}

3. První procesor vypisující základní informace o nalezených konstruktorech

Minule jsme si ukázali, jak lze vytvořit jednoduchý procesor pro určené typy elementů a jakým způsobem je možné pro některé elementy v AST zjistit jejich pozici ve zdrojovém souboru. Zkusme si nyní vytvořit procesor, který zpracuje všechny nalezené konstruktory. Základní princip již známe – vytvoříme potomka třídy AbstractProcessor a s využitím generického typu určíme, jaké typy elementů se budou tímto procesorem zpracovávat. Vlastní zpracování zajišťuje metoda process(), která je automaticky zavolána při průchodu AST. U konstruktorů, které jsou v knihovně Spoon reprezentovány objekty implementujícími rozhraní CtConstructor, lze zjistit jejich pozici ve zdrojovém kódu, jejich jméno i takzvanou signaturu (o signaturách jsem se zmiňoval již například v tomto článku). Celý procesor bude vypadat následovně a nebude se tedy příliš lišit od již popsaných procesorů (až na zjištění signatury):

import spoon.processing.AbstractProcessor;
import spoon.reflect.declaration.CtConstructor;
import spoon.reflect.cu.SourcePosition;
 
public class ConstructorsProcessor extends AbstractProcessor<CtConstructor> {
    public void process(CtConstructor element) {
        SourcePosition sp = element.getPosition();
        String position = sp == null ? "unknown" : sp.toString();
        String name = element.getSimpleName();
        String signature = element.getSignature();
        System.out.println("constructor '" + name + "' with signature '" + signature + "' declared at:" + sp);
    }
}

4. Překlad a použití prvního procesoru

Překlad prvního procesoru se provede stejným způsobem, který již známe z úvodního článku:

javac -cp spoon-core-5.3.0-jar-with-dependencies.jar ConstructorsProcessor.java

Zkusme si nyní procesor spustit s třídou EmptyClass:

java -cp .:spoon-core-5.3.0-jar-with-dependencies.jar spoon.Launcher -p ConstructorsProcessor -i EmptyClass.java
 
constructor '<init>' with signature 'EmptyClass()' declared at:(/home/tester/spoon/EmptyClass.java:1)

Z výpisu můžeme vidět, že se ve třídě nalezl implicitní konstruktor, i když ve zdrojovém kódu se tento konstruktor nenachází. Spoon tento konstruktor do vytvářeného AST přidal, protože to odpovídá JLS (Java Language Specification).

Druhý test provedeme s třídou ManyConstructors:

java -cp .:spoon-core-5.3.0-jar-with-dependencies.jar spoon.Launcher -p ConstructorsProcessor -i ManyConstructors.java
 
constructor '<init>' with signature 'ManyConstructors()' declared at:(/home/tester/spoon/ManyConstructors.java:2)
constructor '<init>' with signature 'ManyConstructors(double)' declared at:(/home/tester/spoon/ManyConstructors.java:19)
constructor '<init>' with signature 'ManyConstructors(double,double)' declared at:(/home/tester/spoon/ManyConstructors.java:21)
constructor '<init>' with signature 'ManyConstructors(double,double,double)' declared at:(/home/tester/spoon/ManyConstructors.java:23)
constructor '<init>' with signature 'ManyConstructors(float)' declared at:(/home/tester/spoon/ManyConstructors.java:12)
constructor '<init>' with signature 'ManyConstructors(float,float)' declared at:(/home/tester/spoon/ManyConstructors.java:15)
constructor '<init>' with signature 'ManyConstructors(int)' declared at:(/home/tester/spoon/ManyConstructors.java:4)
constructor '<init>' with signature 'ManyConstructors(int,int)' declared at:(/home/tester/spoon/ManyConstructors.java:6)
constructor '<init>' with signature 'ManyConstructors(java.lang.String)' declared at:(/home/tester/spoon/ManyConstructors.java:8)
constructor '<init>' with signature 'ManyConstructors(java.lang.String[])' declared at:(/home/tester/spoon/ManyConstructors.java:10)

Povšimněte si rozdílné signatury konstruktorů, zejména pak signatury posledního konstruktoru, kde se … (variabilní počet parametrů) převedl na pole řetězců (opět podle JLS).

5. Druhý procesor vypisující počet parametrů konstruktoru a počet příkazů v jeho těle

Druhý procesor, který si dnes ukážeme, bude nepatrně složitější, protože v něm budeme vypisovat jak počet parametrů konstruktoru (zatím jen počet, ne jména nebo typy) i počet příkazů, které jsou uvedeny (ať již explicitně či implicitně) v jeho těle. Příkazy se získají voláním CtConstructor.getBody().get­Statements() vracející seznam, parametry se získají voláním CtConstructor.getParameters():

import spoon.processing.AbstractProcessor;
import spoon.reflect.declaration.CtConstructor;
import spoon.reflect.cu.SourcePosition;
 
public class ConstructorsProcessor2 extends AbstractProcessor<CtConstructor> {
    public void process(CtConstructor element) {
        SourcePosition sp = element.getPosition();
        String position = sp == null ? "unknown" : sp.toString();
        String name = element.getSimpleName();
        String signature = element.getSignature();
 
        int statements = element.getBody().getStatements().size();
        int parameters = element.getParameters().size();
 
        System.out.println("constructor '" + name + "' with signature '" + signature + "' declared at:" + sp);
        System.out.println("    parameters: " + parameters);
        System.out.println("    statements: " + statements);
    }
}

6. Otestování druhého procesoru

Opět si tento procesor odzkoušíme na třídách EmptyClass a ManyConstructors:

java -cp .:spoon-core-5.3.0-jar-with-dependencies.jar spoon.Launcher -p ConstructorsProcessor2 -i EmptyClass.java
 
constructor '<init>' with signature 'EmptyClass()' declared at:(/home/tester/spoon/EmptyClass.java:1)
    parameters: 0
    statements: 1

Výsledek je v tomto případě zajímavý, i když očekávatelný – v implicitně vytvořeném konstruktoru se nachází jeden příkaz! O který příkaz se jedná nám opět může prozradit JLS – jde o volání konstruktoru předka (tedy super()), o čemž se ostatně přesvědčíme v následujícím příkladu.

Při této znalosti nás již další test s třídou ManyConstructors nepřekvapí:

java -cp .:spoon-core-5.3.0-jar-with-dependencies.jar spoon.Launcher -p ConstructorsProcessor2 -i ManyConstructors.java
 
constructor '<init>' with signature 'ManyConstructors()' declared at:(/home/tester/spoon/ManyConstructors.java:2)
    parameters: 0
    statements: 1
constructor '<init>' with signature 'ManyConstructors(double)' declared at:(/home/tester/spoon/ManyConstructors.java:19)
    parameters: 1
    statements: 1
constructor '<init>' with signature 'ManyConstructors(double,double)' declared at:(/home/tester/spoon/ManyConstructors.java:21)
    parameters: 2
    statements: 1
constructor '<init>' with signature 'ManyConstructors(double,double,double)' declared at:(/home/tester/spoon/ManyConstructors.java:23)
    parameters: 3
    statements: 1
constructor '<init>' with signature 'ManyConstructors(float)' declared at:(/home/tester/spoon/ManyConstructors.java:12)
    parameters: 1
    statements: 2
constructor '<init>' with signature 'ManyConstructors(float,float)' declared at:(/home/tester/spoon/ManyConstructors.java:15)
    parameters: 2
    statements: 3
constructor '<init>' with signature 'ManyConstructors(int)' declared at:(/home/tester/spoon/ManyConstructors.java:4)
    parameters: 1
    statements: 1
constructor '<init>' with signature 'ManyConstructors(int,int)' declared at:(/home/tester/spoon/ManyConstructors.java:6)
    parameters: 2
    statements: 1
constructor '<init>' with signature 'ManyConstructors(java.lang.String)' declared at:(/home/tester/spoon/ManyConstructors.java:8)
    parameters: 1
    statements: 1
constructor '<init>' with signature 'ManyConstructors(java.lang.String[])' declared at:(/home/tester/spoon/ManyConstructors.java:10)
    parameters: 1
    statements: 1

Poznámka: pokud si procesor předěláte takovým způsobem, aby detekoval metody a ne konsturktory, zjistíte, že u nestatických metod je jeden parametr navíc – jedná se o this.

7. Výpis jednotlivých příkazů uvnitř těla konstruktorů a modifikátorů konstruktorů

Poslední procesor, který bude vypisovat informace o všech nalezených konstruktorech, je opět složitější, protože zjistí a vypíše všechny příkazy uvnitř těla konstruktoru a navíc ještě vypíše explicitně zapsané modifikátory (public, private, protected). Pokud by se namísto konstruktorů zjišťovaly informace o metodách, bylo by možné zjistit i další modifikátory, například static, strictfp apod. Povšimněte si, že modifikátory se vrací ve formě množiny (Set), jejíž prvky jsou typu ModifierKind. Příkazy se vrací ve formě seznamu, ovšem pokud by se v konstruktoru nacházely další podbloky, každý by byl opět reprezentován seznamem, který „zastřešují“ objekty typu CtBlock (ten nalezneme i v programových smyčkách, podmínkových konstrukcích apod.). Podívejme se na zdrojový kód dnešního třetího procesoru:

import java.util.Set;
 
import spoon.processing.AbstractProcessor;
import spoon.reflect.declaration.CtConstructor;
import spoon.reflect.cu.SourcePosition;
import spoon.reflect.declaration.ModifierKind;
import spoon.reflect.code.CtStatement;
 
public class ConstructorsProcessor3 extends AbstractProcessor<CtConstructor> {
    public void process(CtConstructor element) {
        SourcePosition sp = element.getPosition();
        String position = sp == null ? "unknown" : sp.toString();
        String name = element.getSimpleName();
        String signature = element.getSignature();
 
        int statements = element.getBody().getStatements().size();
        int parameters = element.getParameters().size();
        Set<ModifierKind> modifiers = element.getModifiers();
 
        System.out.println("constructor '" + name + "' with signature '" + signature + "' declared at:" + sp);
        System.out.println("    parameters: " + parameters);
        System.out.println("    statements: " + statements);
        for (ModifierKind modifier : modifiers) {
            System.out.println("    modifier " + modifier);
        }
        System.out.println("    body:");
        for (CtStatement statement: element.getBody().getStatements()) {
            System.out.println("        " +    statement);
        }
        System.out.println();
    }
}

8. Otestování třetího procesoru

U popisu předchozího procesoru jsem tvrdil, že u konstruktorů s prázdným tělem (a tedy i u implicitně vytvořeného konstruktoru) se jako první příkaz automaticky volá konstruktor předka, tedy super(). Nyní se o platnosti tohoto tvrzení můžeme velmi snadno přesvědčit:

java -cp .:spoon-core-5.3.0-jar-with-dependencies.jar spoon.Launcher -p ConstructorsProcessor3 -i EmptyClass.java
 
constructor '<init>' with signature 'EmptyClass()' declared at:(/home/tester/spoon/EmptyClass.java:1)
    parameters: 0
    statements: 1
    modifier public
    body:
        super()

Vidíme, že se v případě implicitně vytvořeného konstruktoru skutečně do jeho těla vloží volání super(). Navíc má tento konstruktor modifikátor public.

V případě třídy ManyConstructors si povšimněte modifikátorů jednotlivých konstruktorů a samozřejmě taktéž toho, že super() se volá i v konstruktorech s dalšími příkazy:

java -cp .:spoon-core-5.3.0-jar-with-dependencies.jar spoon.Launcher -p ConstructorsProcessor3 -i ManyConstructors.java
 
constructor '<init>' with signature 'ManyConstructors()' declared at:(/home/tester/spoon/ManyConstructors.java:2)
    parameters: 0
    statements: 1
    body:
        super()
 
constructor '<init>' with signature 'ManyConstructors(double)' declared at:(/home/tester/spoon/ManyConstructors.java:19)
    parameters: 1
    statements: 1
    modifier private
    body:
        super()
 
constructor '<init>' with signature 'ManyConstructors(double,double)' declared at:(/home/tester/spoon/ManyConstructors.java:21)
    parameters: 2
    statements: 1
    modifier protected
    body:
        super()
 
constructor '<init>' with signature 'ManyConstructors(double,double,double)' declared at:(/home/tester/spoon/ManyConstructors.java:23)
    parameters: 3
    statements: 1
    modifier public
    body:
        super()
 
constructor '<init>' with signature 'ManyConstructors(float)' declared at:(/home/tester/spoon/ManyConstructors.java:12)
    parameters: 1
    statements: 2
    body:
        super()
        java.lang.System.out.println(x)
 
constructor '<init>' with signature 'ManyConstructors(float,float)' declared at:(/home/tester/spoon/ManyConstructors.java:15)
    parameters: 2
    statements: 3
    body:
        super()
        java.lang.System.out.println(x)
        java.lang.System.out.println(y)
 
constructor '<init>' with signature 'ManyConstructors(int)' declared at:(/home/tester/spoon/ManyConstructors.java:4)
    parameters: 1
    statements: 1
    body:
        super()
 
constructor '<init>' with signature 'ManyConstructors(int,int)' declared at:(/home/tester/spoon/ManyConstructors.java:6)
    parameters: 2
    statements: 1
    body:
        super()
 
constructor '<init>' with signature 'ManyConstructors(java.lang.String)' declared at:(/home/tester/spoon/ManyConstructors.java:8)
    parameters: 1
    statements: 1
    body:
        super()
 
constructor '<init>' with signature 'ManyConstructors(java.lang.String[])' declared at:(/home/tester/spoon/ManyConstructors.java:10)
    parameters: 1
    statements: 1
    body:
        super()

9. Procesor pro detekci všech programových smyček

Zpracování metod se v mnoha ohledech podobá zpracování konstruktorů, takže se raději podívejme na další typy programových konstrukcí v Javě, které mají svůj obraz ve vytvořeném AST. Jednou z těchto konstrukcí je obecná programová smyčka reprezentovaná objektem implementujícím rozhraní CtLoop. V programech samozřejmě neexistují žádné obecné smyčky, ale jen jejich konkrétní implementace, tj. CtDo, CtWhile, CtFor (ta představuje počítanou smyčku for) a konečně CtForEach (ta představuje for nad iterátorem). Pokud však pracujeme s objekty typu CtLoop, můžeme o smyčce zjistit jen základní informace – tělo smyčky (nikoli však například podmínku):

import java.util.Set;
 
import spoon.processing.AbstractProcessor;
import spoon.reflect.cu.SourcePosition;
import spoon.reflect.code.CtLoop;
import spoon.reflect.code.CtStatement;
 
public class LoopDetector extends AbstractProcessor<CtLoop> {
    public void process(CtLoop element) {
        SourcePosition sp = element.getPosition();
        String position = sp == null ? "unknown" : sp.toString();
        CtStatement loopStatement = element.getBody();

        System.out.println("loop: " + loopStatement + " declared at:" + sp);
        System.out.println();
    }
}

10. Otestování čtvrtého procesoru

Tento procesor si otestujeme na třídách WhileLoop1 a Loops.

java -cp .:spoon-core-5.3.0-jar-with-dependencies.jar spoon.Launcher -p LoopDetector -i WhileLoop1
 
loop: {
    java.lang.System.out.println(i);
    i++;
} declared at:(/home/tester/spoon/WhileLoop1.java:5)
java -cp .:spoon-core-5.3.0-jar-with-dependencies.jar spoon.Launcher -p LoopDetector -i Loops
 
loop: {
    java.lang.System.out.println(i);
    i++;
} declared at:(/home/tester/temp/presentations/spoon/Loops.java:5)
 
loop: {
    java.lang.System.out.println(i);
    i++;
} declared at:(/home/tester/temp/presentations/spoon/Loops.java:11)
 
loop: {
    java.lang.System.out.println(i);
} declared at:(/home/tester/temp/presentations/spoon/Loops.java:16)

Povšimněte si, že se vždy vypíše celé tělo smyčky, protože objekty typu CtStatement lze převést na (čitelnou) řetězcovou podobu.

11. Procesor pro zpracování informací o programových smyčkách typu while

Jakým způsobem je však možné získat další informace o nalezené programové smyčce, například podmínku, která se testuje v každé iteraci (resp. před či po každé iteraci)? U procesoru pro obecné smyčky CtLoop to sice není snadné, protože by se musel testovat konkrétní typ každého objektu a provádět přetypování (to v Javě není příliš idiomatický kód), není však žádný problém si vytvořit specializovaný procesor například jen pro smyčky typu while. U těchto smyček se již dá podmínka získat metodou CtWhile.getLoopingExpression:

bitcoin_skoleni

import java.util.Set;
 
import spoon.processing.AbstractProcessor;
import spoon.reflect.cu.SourcePosition;
import spoon.reflect.code.CtWhile;
import spoon.reflect.code.CtStatement;
import spoon.reflect.code.CtExpression;
 
public class WhileLoopDetector extends AbstractProcessor<CtWhile> {
    public void process(CtWhile element) {
        SourcePosition sp = element.getPosition();
        String position = sp == null ? "unknown" : sp.toString();
        CtStatement loopStatement = element.getBody();
        CtExpression loopingExpression = element.getLoopingExpression();
 
        System.out.println("loop: " + loopStatement + " declared at:" + sp);
        System.out.println("expression (test): " + loopingExpression);
        System.out.println();
    }
}

12. Otestování pátého procesoru

Procesor pro programové smyčky typu while si otestujeme na třídě WhileLoop1Loops:

java -cp .:spoon-core-5.3.0-jar-with-dependencies.jar spoon.Launcher -p WhileLoopDetector -i WhileLoop1.java
 
loop: {
    java.lang.System.out.println(i);
    i++;
} declared at:(/home/tester/temp/presentations/spoon/WhileLoop1.java:5)
expression (test): i <= 10
java -cp .:spoon-core-5.3.0-jar-with-dependencies.jar spoon.Launcher -p WhileLoopDetector -i Loops.java
 
loop: {
    java.lang.System.out.println(i);
    i++;
} declared at:(/home/tester/temp/presentations/spoon/Loops.java:11)
expression (test): i <= 10

V obou případech se tedy našla jedna programová smyčka typu while se stejnou podmínkou.

13. Použité třídy a rozhraní knihovny Spoon

  1. spoon.processing.AbstractProcessor
    http://spoon.gforge.inria­.fr/mvnsites/spoon-core/apidocs/spoon/proces­sing/AbstractProcessor.html
  2. spoon.reflect.declaration.CtElement
    http://spoon.gforge.inria­.fr/mvnsites/spoon-core/apidocs/spoon/reflec­t/declaration/CtElement.html
  3. spoon.reflect.declaration.CtClass
    http://spoon.gforge.inria­.fr/mvnsites/spoon-core/apidocs/spoon/reflec­t/declaration/CtClass.html
  4. spoon.reflect.declaration.CtConstructor
    http://spoon.gforge.inria­.fr/mvnsites/spoon-core/apidocs/spoon/reflec­t/declaration/CtConstructor­.html
  5. spoon.reflect.declaration.ModifierKind
    http://spoon.gforge.inria­.fr/mvnsites/spoon-core/apidocs/spoon/reflec­t/declaration/ModifierKin­d.html
  6. spoon.reflect.code.CtLoop
    http://spoon.gforge.inria­.fr/mvnsites/spoon-core/apidocs/spoon/reflec­t/code/CtLoop.html
  7. spoon.reflect.code.CtWhile
    http://spoon.gforge.inria­.fr/mvnsites/spoon-core/apidocs/spoon/reflec­t/code/CtWhile.html
  8. spoon.reflect.code.CtStatement
    http://spoon.gforge.inria­.fr/mvnsites/spoon-core/apidocs/spoon/reflec­t/code/CtStatement.html
  9. spoon.reflect.code.CtExpression
    http://spoon.gforge.inria­.fr/mvnsites/spoon-core/apidocs/spoon/reflec­t/code/CtExpression.html
  10. spoon.reflect.cu.SourcePosition
    http://spoon.gforge.inria­.fr/mvnsites/spoon-core/apidocs/spoon/reflec­t/cu/SourcePosition.html
  11. spoon.reflect.reference.CtVa­riableReference
    http://spoon.gforge.inria­.fr/mvnsites/spoon-core/apidocs/spoon/reflec­t/reference/CtVariableRefe­rence.html

14. Odkazy na Internetu

  1. Spoon – Source Code Analysis and Transformation for Jav
    http://spoon.gforge.inria.fr/
  2. Project Filelist for Spoon
    https://gforge.inria.fr/frs/?grou­p_id=73
  3. Spoon na GitHubu
    https://github.com/INRIA/spoon
  4. Instance Jenkinsu, v níž se překládá Spoon
    https://ci.inria.fr/sos/
  5. JavaParser: Java Parser and Abstract Syntax Tree
    http://javaparser.org/
  6. Javaparser na GitHubu
    https://github.com/javapar­ser/javaparser
  7. FindBugs Fact Sheet
    http://findbugs.sourcefor­ge.net/factSheet.html
  8. Open Source ByteCode Libraries in Java
    http://java-source.net/open-source/bytecode-libraries
  9. ASM Home page
    http://asm.ow2.org/
  10. Seznam nástrojů využívajících projekt ASM
    http://asm.ow2.org/users.html
  11. ObjectWeb ASM (Wikipedia)
    http://en.wikipedia.org/wi­ki/ObjectWeb_ASM
  12. Java Bytecode BCEL vs ASM
    http://james.onegoodcooki­e.com/2005/10/26/java-bytecode-bcel-vs-asm/
  13. BCEL Home page
    http://commons.apache.org/bcel/
  14. Byte Code Engineering Library (před verzí 5.0)
    http://bcel.sourceforge.net/
  15. Byte Code Engineering Library (verze >= 5.0)
    http://commons.apache.org/pro­per/commons-bcel/
  16. BCEL Manual
    http://commons.apache.org/bcel/ma­nual.html
  17. Byte Code Engineering Library (Wikipedia)
    http://en.wikipedia.org/wiki/BCEL
  18. BCEL Tutorial
    http://www.smfsupport.com/sup­port/java/bcel-tutorial!/
  19. Bytecode Engineering
    http://book.chinaunix.net/spe­cial/ebook/Core_Java2_Volu­me2AF/0131118269/ch13lev1sec6­.html
  20. Bytecode Outline plugin for Eclipse (screenshoty + info)
    http://asm.ow2.org/eclipse/index.html
  21. Javassist
    http://www.jboss.org/javassist/
  22. Byteman
    http://www.jboss.org/byteman
  23. Java programming dynamics, Part 7: Bytecode engineering with BCEL
    http://www.ibm.com/develo­perworks/java/library/j-dyn0414/
  24. Using javap
    http://www.idevelopment.in­fo/data/Programming/java/mis­cellaneous_java/Using_javap­.html
  25. Examine class files with the javap command
    http://www.techrepublic.com/ar­ticle/examine-class-files-with-the-javap-command/5815354
  26. aspectj (Eclipse)
    http://www.eclipse.org/aspectj/
  27. Aspect-oriented programming (Wikipedia)
    http://en.wikipedia.org/wi­ki/Aspect_oriented_program­ming
  28. AspectJ (Wikipedia)
    http://en.wikipedia.org/wiki/AspectJ
  29. EMMA: a free Java code coverage tool
    http://emma.sourceforge.net/
  30. Cobertura
    http://cobertura.sourceforge.net/
  31. jclasslib bytecode viewer
    http://www.ej-technologies.com/products/jclas­slib/overview.html
  32. Abstract syntax tree
    https://en.wikipedia.org/wi­ki/Abstract_syntax_tree

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.