Zpracovala: Marta Václavíková
Vedoucí
projektu, korektury, závěrečná revize: Pavel Herout
Jad je Java dekompilátor, tj. program, který čte jeden nebo více Java class souborů a konvertuje je zpět do zdrojových souborů java, jež mohou být většinou (viz též dále) opět zkompilovány.
Jad je napsán celý v C++ a většinou pracuje rychleji než dekompilátory napsané v Javě.
Jad je zdarma pouze pro nekomerční použití.
Jad nepoužívá JVM pro svůj běh, není nutná žádná instalace.
Stačí rozbalit soubor jad.zip, který obsahuje 2 soubory:Pro dekompilaci jednoho class souboru Priklad1.class stačí napsat:
jad Priklad1.classVznikne soubor Priklad1.jad v aktuálním adresáři.
Zadáme-li název class souboru třídy obsahující vnitřní třídy, program sám vyhledá v aktuálním adresáři class soubory daných vniřních tříd. Nenalezne-li je, vypíše upozornění.
Anonymní vnitřní třídy umístí do konstruktoru dané vnější třídy (což pak většinou znamená, že zdrojový soubor nelze okamžitě přeložit programem javac.exe, případně jej lze přeložit, ale výsledný program není funkční).
Dekompilace všech class souborů v aktuálním adresáři:jad *.classDekompilace všech class souborů v podadresářích (poměrně netypický zápis pomocí ** znamená "všechny případné podadresáře"):
jad adr1/**/*.class
Přepíše již existující soubor s příponou.jad bez varování a následného schválení.
Výstupní soubor má příponu .java.
Např.: jad -sjava priklad1.class vytvoří soubor priklad1.javaVýsledek činnosti jad je posílán na standardní výstup. Typické použití je v případě, kdy chceme výstupní soubor pojmenovat zcela libovolným jménem.
Např. jad -p priklad1.class > pokus.java vytvoří soubor pokus.java
Ukázkový Hlavni.java soubor obsahuje dvě vnější třídy Hlavni, Vnejsi a rozhraní Rozhrani. Třída Hlavni obsahuje vnitřní třídu Vnitrni a anonymní vnitřní třídu.
Pomocí příkazu javac Hlavni.java se vytvoří pět class souborů: Hlavni.class, Rozhrani.class, Vnejsi.class, Hlavni$1.class, Hlavni$Vnitrni.class
Zadáním příkazu jad Hlavni.class Vnejsi.class Rozhrani.class vzniknou výstupní soubory Hlavni.jad, Rozhrani.jad, Vnejsi.jad.
Soubor Hlavni.java
public class Hlavni { public int hlavniAtribut; |
Soubor Hlavni.jad
import java.io.PrintStream; public class Hlavni { public int hlavniAtribut; |
class Vnitrni { private int vnitrniAtribut; public Vnitrni(int i) { vnitrniAtribut = i; } public void vnitrniMetoda() { System.out.println("Vnitřní metoda - " + vnitrniAtribut); } } |
class Vnitrni { public void vnitrniMetoda() { System.out.println("Vnit\u0159n\355 metoda - " + vnitrniAtribut); } private int vnitrniAtribut; public Vnitrni(int i) { vnitrniAtribut = i; } } |
public Rozhrani r = new Rozhrani () { public void metodaRozhrani () { System.out.println("Vnitřní Anonymní Metoda"); } }; |
public Rozhrani r; public Hlavni() { r = new Rozhrani() { public void metodaRozhrani() { System.out.println("Vnit\u0159n\355 Anonymn\355 Metoda"); } }; } |
public void hlavniMetoda() { System.out.println("Hlavní Metoda - " + hlavniAtribut); Vnitrni vn = new Vnitrni(1); vn.vnitrniMetoda(); } |
public void hlavniMetoda() { System.out.println("Hlavn\355 Metoda - " + hlavniAtribut); Vnitrni vnitrni = new Vnitrni(1); vnitrni.vnitrniMetoda(); } |
public static void main(String[] args){ Hlavni h = new Hlavni(); Vnejsi v = new Vnejsi(2); h.hlavniAtribut = 5; h.hlavniMetoda(); v.vnejsiMetoda(); h.r.metodaRozhrani(); } |
public static void main(String args[]) { Hlavni hlavni = new Hlavni(); Vnejsi vnejsi = new Vnejsi(2); hlavni.hlavniAtribut = 5; hlavni.hlavniMetoda(); vnejsi.vnejsiMetoda(); hlavni.r.metodaRozhrani(); } |
interface Rozhrani { void metodaRozhrani(); } |
Soubor Rozhrani.jad
interface Rozhrani { public abstract void metodaRozhrani(); } |
class Vnejsi { public int vnejsiAtribut; public Vnejsi (int i) { vnejsiAtribut = i; } void vnejsiMetoda() { System.out.println("Vnější Metoda - " + vnejsiAtribut); } } |
Soubor Vnejsi.jad
import java.io.PrintStream; class Vnejsi { public Vnejsi(int i) { vnejsiAtribut = i; } void vnejsiMetoda() { System.out.println("Vn\u011Bj\u0161\355 Metoda - " + vnejsiAtribut); } public int vnejsiAtribut; } |
Příklad ukazuje tři třídy, které se navzájem volají. Třídy jsou uloženy v souborech Hlavni.java, Rodic.java, Potomek.java.
Pomocí příkazu javac Hlavni.java se vytvoří soubory Hlavni.class, Rodic.class, Potomek.class.
Zadáním příkazu jad Hlavni.class Rodic.class Potomek.class vzniknou výstupní soubory Hlavni.jad, Rodic.jad, Potomek.jad.
Soubor Rodic.java
public class Rodic { public int i; public Rodic(int i) { this.i = i; } public int getI() { return i; } } |
    |
Soubor Rodic.jad
public class Rodic { public Rodic(int j) { i = j; } public int getI() { return i; } public int i; } |
Soubor Potomek.java
public class Potomek extends Rodic { public int k; public Potomek(int i, int k) { super(i); this.k = k; } public int getK() { return k; } } |
    |
Soubor Potomek.jad
public class Potomek extends Rodic { public Potomek(int i, int j) { super(i); k = j; } public int getK() { return k; } public int k; } |
Soubor Hlavni.java
public class Hlavni { public static void main(String[] args){ Rodic r = new Rodic(1); Potomek p = new Potomek(2,3); System.out.println(r.getI()); System.out.println(p.getI()); System.out.println(p.getK()); } } |
    |
Soubor Hlavni.jad
import java.io.PrintStream; public class Hlavni { public Hlavni() { } public static void main(String args[]) { Rodic rodic = new Rodic(1); Potomek potomek = new Potomek(2, 3); System.out.println(rodic.getI()); System.out.println(potomek.getI()); System.out.println(potomek.getK()); } } |
Program Jad dokáže celkem spolehlivě zrekonstruovat původní kód. Zrekonstruovaný kód se liší od původního v několika detailech, jako např. se změní pořadí deklarací atributů a metod, vnitřní anonymní třídy jsou umístěny do konstruktoru vnější třídy, akcentované znaky jsou nahrazeny buď zápisem hodnoty v Unicode nebo oktalově, názvy lokálních proměnných nebo formálních parametrů jsou pozměněny atp.
I přes tyto malé změny je výsledný zdrojový kód velmi dobře čitelný (možná někdy lépe, než původní
zdrojový kód).
Poznámka P.Herouta:
V dokumentaci k Jad se dokonce žertem píše, že by program mohl být použit pro zčitelnění
zdrojového kódu. Po zkušenostech z výuky je třeba říci, že výstup z Jad je mnohem lépe čitelný,
než mnoho "nedbale" napsaných zdrojových programů. Je možné říci, že programátorovi, který naprosto nedbá na "štábní kulturu" může tento program také výrazně zpřehlednit jeho zdrojové kódy.
Pro více informací navštivte domovské stránky dekompilátoru Jad, kde si můžete stáhnout jeho nejnovější verzi:
http://kpdus.tripod.com/jad.html