23 Nisan 2020 Perşembe

javap komutu - Decompiler

Giriş
Decompiler aracıdır.

javap Çıktısı

descriptor Çıktısı
descriptor metod imzasını gösterir
Örnek
Elimizde şöyle bir kod olsun
public class Example {
  public static void main(String[] args) {
    int a = 1;
    a++;
    int b = a * a;
    int c = b - a;
    System.out.println(c);
 }
}
Çıktı şöyle
Classfile Example.class
  ...
public class Example
  ...
  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    ...
}
SourceFile: "Example.java"
Açıklaması şöyle
Descriptor specifies the types of the method’s arguments and its return type. Inside the parentheses we can see the argument types. In our case, there is only one: [Ljava/lang/String;

When a type descriptor begins with [, it indicates an array. Object types follow a specific format: they start with L and end with ;. In this case, the construction specifies a String type: Ljava/lang/String;

The V outside the parentheses means a void return type of our method.

Therefore, the main method accepts an array of String: [Ljava/lang/String; and returns void.
Code Çıktısı
Çıktı şöyle. Bytecode talimatlarını gösteri
Code:
  stack=2, locals=4, args_size=1
    0: iconst_1
    1: istore_1
    2: iinc          1, 1
    5: iload_1
    6: iload_1
    7: imul
    8: istore_2
    9: iload_2
    10: iload_1
    11: isub
    12: istore_3
    13: getstatic     #2  // Field java/lang/System.out:Ljava/io/PrintStream;
    16: iload_3
    17: invokevirtual #3. // Method java/io/PrintStream.println:(I)V
    20: return
-c seçeneği
Kaynak kodu gösterir.

Örnek
Şöyle yaparız.
> javap -c Default.class
Compiled from "Default.java"
public Default {
  ...
}
Örnek
Elimizde şöyle bir kod olsun.
public class Calculator {
  public int add(int a, int b) {
    return a + b;
  }
}
Şöyle yaparız
$ javap -c Calculator

Compiled from "Calculator.java"
public class Calculator {
  public Calculator();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public int add(int, int);
    Code:
       0: iload_1
       1: iload_2
       2: iadd
       3: ireturn
}
Örnek
Elimizde şöyle bir kod olsun.
public class WideGoto {

  public static void main(String[] args) {
    for (int i = 0; i < 1_000_000_000; ) {
      i += 123456;
      // ... repeat 10K times ...
    }
  }
}
Çıktı olarak şunu alırız
public static void main(java.lang.String[]);
  Code:
    0: iconst_0
    1: istore_1
    2: iload_1
    3: ldc           #2
    5: if_icmplt     13
    8: goto_w        50018     // <<< Here it is! A jump to the end of the loop
    ...
Örnek
Dosyanın ismi A#1.class ise şöyle yaparız
javap -c A\$1
-protected seçeneği
Örnek
Şöyle yaparız
# javap -protected TimestampUtils.class

Compiled from "TimestampUtils.java"
public final class pl.nsn.railway.service.util.TimestampUtils {
  public static java.sql.Timestamp getEpochTimeStamp();
  public static boolean isAfterNow(java.sql.Timestamp);
  public static boolean isBeforeNow(java.sql.Timestamp);
  public static java.sql.Timestamp now();
  public static java.sql.Timestamp nowMinus(long);
  public static java.sql.Timestamp nowPlus(long);
}
-v seçeneği
Bu seçenek en çok hangi Java sürümüne göre derlendiğini bulmak için kullanılır. Bunun dışında aslında bir sürü çıktı da veriyor.

Örnek - Java Sürümü
Şöyle yaparız. Çıktı olarak gördüğümüz sayının - yani 45 - bir anlamı var.
#linux
$ javap -v ./org/apache/log4j/Appender.class | grep major
 major version: 45

#windows
$ javap -v ./org/apache/log4j/Appender.class | grep major
 major version: 45
Burada şu açıklamaya dikkat etmek lazım
To be pedantic, those bytes tell you what version the class has been compiled FOR, not what version compiled it. Java allows you to compile code so that they're compatible with earlier versions of Java. However, this only applies to byte code and format. It will happily compile code that references JDK 6 libraries into a JDK 5 format, for example. The JDK 5 will load the class, but can't run it as the JDK 5 library doesn't have the code referenced from JDK 6.
Örnek
Şöyle yaparız.
$ javap -v HelloWorld.class > with-line.txt
Örnek
Şöyle yaparız.
javap -verbose path/to/ClassFile.class
Örnek
Çıktı olarak şunu alırız. Burada komutun bir sürü çıktı verdiği görülebilir.
Constant pool:
   #1 = Methodref          #9.#18         // java/lang/Object."<init>":()V
   #2 = String             #19            // 中
   #3 = String             #20            // 𩄀
   #4 = Fieldref           #21.#22        // 
... truncated
  #17 = Utf8               UnicodeTest.java
  #18 = NameAndType        #10:#11        // "<init>":()V
  #19 = Utf8               
  #20 = Utf8               𩄀

Hiç yorum yok:

Yorum Gönder