JAVAP - The Java Class File Disassembler

Zpracovala: Marta Václavíková
Vedoucí projektu, korektury, závěrečná revize: Pavel Herout

Příkaz javap rozebírá class soubory (přeložené soubory ve strojovém jazyce bytecode) a přepisuje strojový bytecode do čitelné podoby. Umožňuje efektivní ladění kódu.

Poznámka:
Nečekejte, že tento nástroj provede tzv. "zpětné inženýrství", tj. z dostupného bytecode vytvoří zdrojový text .java.
Jedno z mála rozumných použití pro běžného programátora v Javě je zjištění efektivity kódu -- viz příklad.

Obsah

Syntaxe

javap [ -b ] [ -c ] [ -classpathpath ] [ -extdirs ] [ -help ] [ -J ] [ -l ] [ -package ] [ -private ] [ -protected ] [ -public ] [ -s ] [bootclasspath ] [ -verbose ] názvy class souborů

Názvy zkoumaných .class souborů oddělené mezerou se uvádí za parametry příkazu. Je možné uvést i několik .class souborů najednou. Vnější třídy se uvádějí svým názvem (př. Test), vnořené třídy spolu s názvem nadřazené třídy (př. Test.Vnitrni).

Výpis informací provádí na standardní výstup (stdout).


Popis parametrů

-b

Zpětná kompatibilita s příkazem javap v JDK 1.1. V současnosti nepodporovaná.

-c

Výpis těl jednotlivých metod pomocí instrukcí strojového jazyka bytecode.
(používaný užitečný parametr -- pozn. autora)

Příklad zdrojového kódu:
public class Pozdrav{
  public static void main(String[] args){
	System.out.println("Dobry den");	
  }
}
Příkaz:
 javap -c Pozdrav 
Výsledek:
Compiled from "Pozdrav.java"
public class Pozdrav extends java.lang.Object{
public Pozdrav();
  Code :
     0:	aload_0
     1:	invokespecial   #1; //Method java/lang/Object."":()V
     4:	return

public static void mani(java.lang.String[]);
  Code :
     0: 	getstatic	#2;    //Field java/lang/System.out:Ljava/io/PrintStream;
     3:	ldc	#3;   //String Dobry den
     5:	invokevirtual	#4;   //Method java/io/PrintStream.println:(Ljava/lang/String;)V
     8:	return
}

-classpath <pathlist>

Určuje umístění zkoumaných .class souborů. Přepíše defaultní nastavení nebo proměnnou prostředí CLASSPATH, je-li nastavena. Vždy obsahuje systémové třídy na konci adresy. Adresáře jsou odděleny dvojtečkou (UNIX) nebo středníkem (Windows).

Syntaxe pathlist:    .:<adresa>
např. javac -classpath .:/home/ch/classes:/usr/local/java/classes

-extdirs

Zruší nastavené umístění instalovaných rozšíření. Standardní umístění rozšíření je jre/lib/ext.

-help

Výpis nápovědy k příkazu javap.

-J flag

Posílá flag přímo do runtime systému.

Např.
javap -J-version
javap -J-Djava.security.manager -J-Djava.security.policy=MyPolicy MyClassName

-l

Vypíše čísla řádek a tabulku lokálních proměnných public částí třídy. Informace jsou využívány debuggery.

Čísla řádek jsou vypsána, je-li třída zkompilována bez parametru -o příkazu javac. Lokální proměnné jsou vypsány, je-li třída zkompilována s parametrem -g příkazu javac.

-package (nebo bez parametrů)

Příkaz vypíše název balíku třídy a rodičovské třídy, názvy a typy jejích protected a public atributů a hlavičky protected a public metod s parametry.

-private

Vypíše název balíku třídy a rodičovské třídy, názvy a typy všech atributů třídy a hlavičky všech jejích metod s parametry.

Příklad zdrojového kódu:
package test;

public class Trida{
   public int publicAtribut;
   protected float protectedAtribut;
   private boolean privateAtribut;

   protected void protectedMetoda(int i, float f){}
   private void privateMetoda(){}
   public static void main(String[] args){
        System.out.println("Ahoj");	
   }
}
Příkaz:
javap -private Trida
Výsledek:
Compiled from "Trida.java"
public class test.Trida extends java.lang.Object{
   public int publicAtribut;
   protected float protectedAtribut;
   private boolean privateAtribut;
   public test.Trida();
   protected void protectedMetoda(int, float);
   private void privateMetoda();
   public static void main(java.lang.String[]);
}

-protected

Příkaz vypíše název balíku a rodičovské třídy, názvy a typy jejích protected a public atributů a hlavičky protected a public metod s parametry.

-public

Vypíše název balíku třídy a rodičovské třídy, názvy a typy public atributů třídy a hlavičky jejích public metod s parametry.

-s

Vypíše interní typy značek.

-bootclasspath <pathlist>

Určuje adresu, ze které se nahrávají samozaváděcí třídy (bootstrap class). Standardně samozaváděcí třídy jsou třídy implementující jádro Java 2 platform umístěné v jre/lib/rt.jar a jre/lib/i18n.jar.

-verbose

Vypíše velikost zásobníku, počet locals a args jednotlivých metod.

Příklad použití příkazu javap při ladění kódu

Zdrojové kódy dvou podobných metod:

String concat1(String str1, String str2) {
        return str1 + str2;
    }

   void concat2(StringBuffer str1, String str2) {
        str1.append(str2);
   }

Po zadání příkazu javap s parametrem -c se vypíše bytecode jednotlivých metod:

Method java.lang.String concat1(java.lang.String, java.lang.String)
   0 new #2 
   3 dup
   4 invokespecial #3 
   7 aload_1
   8 invokevirtual #4 
  11 aload_2
  12 invokevirtual #4 
  15 invokevirtual #5 
  18 areturn

Method void concat2(java.lang.StringBuffer, java.lang.String)
   0 aload_1
   1 aload_2
   2 invokevirtual #4 
   5 pop
   6 return

Metoda concat1() volá celkem 5 metod : new, invokespecial a 3x invokevirtual. Naopak metoda concat() volá jen jednou metodu invokevirtual. Jednoznačně vidíme, že pro slučování řetězců je výhodnější používání typu StringBuffer namísto String.

Příkaz javap se hodí pro analýzu programů s podobnou funkcí. Pomocí jejich přepisu do bytecode se určí efektivnější kód. Pozor však na skutečnost, že bytecode není konečnou podobou programu, protože just-in-time kompilátor většinou kód dále optimalizuje. Proto nelze bytecode brát jako konečnou podobu programu.


Zdroje

http://java.sun.com/j2se/1.3/docs/tooldocs/solaris/javap.html

http://developer.java.sun.com/developer/TechTips/index.html