第二章 中間表示

  1. java字節(jié)碼作為中間表示(使用javap命令查看)
Classfile /home/jiansun/mydemo/sootdemo/Add.class
  Last modified 2019-8-7; size 488 bytes
  MD5 checksum 74331c11abb06b528003d93bae6e9d83
  Compiled from "Add.java"
public class Add
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #6.#17         // java/lang/Object."<init>":()V
   #2 = Methodref          #5.#18         // Add.addTwoNum:(II)I
   #3 = Fieldref           #19.#20        // java/lang/System.out:Ljava/io/PrintStream;
   #4 = Methodref          #21.#22        // java/io/PrintStream.println:(I)V
   #5 = Class              #23            // Add
   #6 = Class              #24            // java/lang/Object
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               main
  #12 = Utf8               ([Ljava/lang/String;)V
  #13 = Utf8               addTwoNum
  #14 = Utf8               (II)I
  #15 = Utf8               SourceFile
  #16 = Utf8               Add.java
  #17 = NameAndType        #7:#8          // "<init>":()V
  #18 = NameAndType        #13:#14        // addTwoNum:(II)I
  #19 = Class              #25            // java/lang/System
  #20 = NameAndType        #26:#27        // out:Ljava/io/PrintStream;
  #21 = Class              #28            // java/io/PrintStream
  #22 = NameAndType        #29:#30        // println:(I)V
  #23 = Utf8               Add
  #24 = Utf8               java/lang/Object
  #25 = Utf8               java/lang/System
  #26 = Utf8               out
  #27 = Utf8               Ljava/io/PrintStream;
  #28 = Utf8               java/io/PrintStream
  #29 = Utf8               println
  #30 = Utf8               (I)V
{
  public Add();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 1: 0

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=4, args_size=1
         0: bipush        13
         2: istore_2
         3: bipush        17
         5: istore_3
         6: iload_2
         7: iload_3
         8: invokestatic  #2                  // Method addTwoNum:(II)I
        11: istore_1
        12: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
        15: iload_1
        16: invokevirtual #4                  // Method java/io/PrintStream.println:(I)V
        19: return
      LineNumberTable:
        line 4: 0
        line 5: 3
        line 6: 6
        line 7: 12
        line 8: 19

  public static int addTwoNum(int, int);
    descriptor: (II)I
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=4, args_size=2
         0: bipush        7
         2: istore_2
         3: bipush        8
         5: istore_3
         6: iload_0
         7: iload_1
         8: iadd
         9: iconst_2
        10: imul
        11: ireturn
      LineNumberTable:
        line 11: 0
        line 12: 3
        line 13: 6
}
SourceFile: "Add.java"
  1. baf中間表示
    • 把200多種不同的字節(jié)碼精簡為60種
    • 沒有常量池屑那,直接通過函數(shù)名和字段名訪問方法和字段
    • 使用word/dword顯式定義局部變量(64/32位)
    • 無需過多關(guān)注變量類型,例如int怠晴、short、long等相加的指令勺美,在baf中統(tǒng)稱為相加指令
public class Add extends java.lang.Object
{

    public void <init>()
    {
        word r0;

        r0 := @this: Add;
        load.r r0;
        specialinvoke <java.lang.Object: void <init>()>;
        return;
    }

    public static void main(java.lang.String[])
    {
        word r0;

        r0 := @parameter0: java.lang.String[];
        push 13;
        push 17;
        staticinvoke <Add: int addTwoNum(int,int)>;
        store.i r0;
        staticget <java.lang.System: java.io.PrintStream out>;
        load.i r0;
        virtualinvoke <java.io.PrintStream: void println(int)>;
        return;
    }

    public static int addTwoNum(int, int)
    {
        word i0, i1, b2;

        i0 := @parameter0: int;
        i1 := @parameter1: int;
        push 7;
        store.b b2;
        push 8;
        store.b b2;
        load.i i0;
        load.i i1;
        add.i;
        push 2;
        mul.i;
        return.i;
    }
}
  1. jimple作為中間表示

    soot中Jimple語句類型

    • 負(fù)責(zé)過程內(nèi)控制流的語句:IfStmt , GotoStmt , TableSwitchStmt , LookupSwitchStmt

    • 負(fù)責(zé)過程間的控制流語句:InvokeStmt , ReturnStmt , ReturnVoidStmt.

    • 監(jiān)控語句:EnterMonitorStmt , ExitMonitorStmt.

    • ThrowStmt , RetStmt

  • jimple是類型化的冬殃、三地址的、基于語句的中間代碼

  • Java字節(jié)碼有大約200個(gè)不同的字節(jié)碼指令募寨,BAF大約有60個(gè)族展,而JIMPLE有15個(gè)。

  • 因?yàn)槠渚o湊型拔鹰,利于分析和優(yōu)化仪缸。

  • 有類型和命名的局部變量可以改進(jìn)分析

  • 運(yùn)算符是無類型的,而baf的運(yùn)算符是有類型的(add.i列肢,add.f恰画,add.d或add.l)宾茂。在轉(zhuǎn)換成baf時(shí),不再需要有類型的運(yùn)算符(因?yàn)榫植孔兞坑蓄愋停?/p>

Map m = new HashMap();
m.get("key");

//becomes the following JIMPLE code:

java.util.HashMap $r1, r2;
$r1 = new java.util.HashMap;
specialinvoke $r1.<java.util.HashMap: void <init>()>();
r2 = $r1;
//這里知道了r2的類型是hashmap拴还,如果不知道的話刻炒,interfaceinvoke可以映射到實(shí)現(xiàn)Map接口的任何方法。
interfaceinvoke r2.<java.util.Map:     
java.lang.Object get(java.lang.Object)>("key");
  • 局部變量都在方法的頂部聲明自沧,包括引用數(shù)據(jù)類型和基本數(shù)據(jù)類型坟奥。
  • identity語句定義了使用特殊值預(yù)加載的局部變量,如this或方法參數(shù)
  • jimple類似于簡單的Java代碼(所以叫做jimple)
  • 賦值語句占主導(dǎo)地位


    1565142816842.png

? jimple代碼優(yōu)化之后拇厢,可以重新轉(zhuǎn)化成字節(jié)碼文件爱谁,在虛擬中運(yùn)行。

public class Add extends java.lang.Object
{

    public void <init>()
    {
        Add r0;

        r0 := @this: Add;
        specialinvoke r0.<java.lang.Object: void <init>()>();
        return;
    }

    public static void main(java.lang.String[])
    {
        java.lang.String[] r0;
        byte b0, b1;
        int i2;
        java.io.PrintStream $r1;

        r0 := @parameter0: java.lang.String[];
        b0 = 13;
        b1 = 17;
        i2 = staticinvoke <Add: int addTwoNum(int,int)>(b0, b1);
        $r1 = <java.lang.System: java.io.PrintStream out>;
        virtualinvoke $r1.<java.io.PrintStream: void println(int)>(i2);
        return;
    }

    public static int addTwoNum(int, int)
    {
        int i0, i1, $i4, $i5;
        byte b2, b3;

        i0 := @parameter0: int;
        i1 := @parameter1: int;
        b2 = 7;
        b3 = 8;
        $i4 = i0 + i1;
        $i5 = $i4 * 2;
        return $i5;
    }
}
  1. Grimp是更易閱讀的中間表示(更像是反編譯的java代碼孝偎,grimp作為反編譯器的基礎(chǔ))


    1565145414041.png

    grimp允許使用new操作访敌,因此更接近java源代碼

public class Add extends java.lang.Object
{

    public void <init>()
    {
        Add r0;

        r0 := @this: Add;
        specialinvoke r0.<java.lang.Object: void <init>()>();
        return;
    }

    public static void main(java.lang.String[])
    {
        java.lang.String[] r0;
        byte b0, b1;
        int i2;
        java.io.PrintStream $r1;

        r0 := @parameter0: java.lang.String[];
        b0 = 13;
        b1 = 17;
        i2 = staticinvoke <Add: int addTwoNum(int,int)>(b0, b1);
        $r1 = <java.lang.System: java.io.PrintStream out>;
        virtualinvoke $r1.<java.io.PrintStream: void println(int)>(i2);
        return;
    }

    public static int addTwoNum(int, int)
    {
        int i0, i1, $i4, $i5;
        byte b2, b3;

        i0 := @parameter0: int;
        i1 := @parameter1: int;
        b2 = 7;
        b3 = 8;
        $i4 = i0 + i1;
        $i5 = $i4 * 2;
        return $i5;
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市衣盾,隨后出現(xiàn)的幾起案子寺旺,更是在濱河造成了極大的恐慌,老刑警劉巖势决,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件阻塑,死亡現(xiàn)場離奇詭異,居然都是意外死亡果复,警方通過查閱死者的電腦和手機(jī)陈莽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來虽抄,“玉大人走搁,你說我怎么就攤上這事÷蹩撸” “怎么了私植?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長车酣。 經(jīng)常有香客問我曲稼,道長,這世上最難降的妖魔是什么骇径? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任躯肌,我火速辦了婚禮,結(jié)果婚禮上破衔,老公的妹妹穿的比我還像新娘清女。我一直安慰自己,他們只是感情好晰筛,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布嫡丙。 她就那樣靜靜地躺著拴袭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪曙博。 梳的紋絲不亂的頭發(fā)上拥刻,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天,我揣著相機(jī)與錄音父泳,去河邊找鬼般哼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛惠窄,可吹牛的內(nèi)容都是我干的蒸眠。 我是一名探鬼主播,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼杆融,長吁一口氣:“原來是場噩夢啊……” “哼楞卡!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起脾歇,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蒋腮,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后藕各,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體池摧,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年座韵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了险绘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片踢京。...
    茶點(diǎn)故事閱讀 40,013評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡誉碴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瓣距,到底是詐尸還是另有隱情黔帕,我是刑警寧澤,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布蹈丸,位于F島的核電站成黄,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏逻杖。R本人自食惡果不足惜奋岁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望荸百。 院中可真熱鬧闻伶,春花似錦、人聲如沸够话。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至畜份,卻和暖如春诞帐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背爆雹。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工停蕉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人钙态。 一個(gè)月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓谷徙,卻偏偏與公主長得像,于是被迫代替她去往敵國和親驯绎。 傳聞我的和親對象是個(gè)殘疾皇子完慧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 一:java概述: 1,JDK:Java Development Kit剩失,java的開發(fā)和運(yùn)行環(huán)境屈尼,java的開發(fā)...
    慕容小偉閱讀 1,789評論 0 10
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,103評論 1 32
  • 一、基礎(chǔ)知識(shí):1拴孤、JVM脾歧、JRE和JDK的區(qū)別:JVM(Java Virtual Machine):java虛擬機(jī)...
    殺小賊閱讀 2,380評論 0 4
  • 一鞭执、基本數(shù)據(jù)類型 注釋 單行注釋:// 區(qū)域注釋:/* */ 文檔注釋:/** */ 數(shù)值 對于byte類型而言...
    龍貓小爺閱讀 4,265評論 0 16
  • 第01章 JAVA簡介第02章 基礎(chǔ)語法第02章 遞歸補(bǔ)充第03章 面向?qū)ο蟮?4章 異常處理第05章 數(shù)組第06...
    順毛閱讀 514評論 0 1