当前位置:   article > 正文

【Java 虚拟机原理】Dalvik 虚拟机 ( 打包 Jar 文件和 Dex 文件 | 反编译 Dex 文件 | 分析 Dex 文件反编译结果 )_含dex的jar .dex的区别

含dex的jar .dex的区别

前言

Dalvik 虚拟机运行的是 Dex 文件 ; Dex 文件并不是最终 DVM 运行的文件 , Dex 文件还需要再次优化为 Odex 文件 , 这才是最终运行在 DVM 上的文件 ;

安装 APK 完毕后 , 运行时 , 或者 使用类加载器加载 Dex 文件时 , 才会生成 Odex 文件 ;

Odex 文件会存放在 /data/dalvik-cache 目录下 ;

在这里插入图片描述





一、打包 Jar 文件和 Dex 文件



Dalvik 虚拟机中运行的是 Dex 文件 , Java 虚拟机运行的是 Jar 文件 ;


1、示例代码


示例代码 :

  • 代码 1 1 1 :
public class Student {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void ageIncrease(){
        synchronized(this) {
            this.age++;
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 代码 2 2 2 :
public class User {
    private int age = 0;

    public synchronized void increase() {
        this.age++;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2、打包 Jar 文件


打包 Jar 文件 :

使用如下命令 , 将 Class 字节码文件打成 Jar 包 :

jar cvf main.jar Student.class User.class
  • 1

输出结果 :

D:\002_Project\004_Java_Learn\Main\out\production\Main>jar cvf main.jar Student.class User.class
已添加清单
正在添加: Student.class(输入 = 889) (输出 = 478)(压缩了 46%)
正在添加: User.class(输入 = 356) (输出 = 251)(压缩了 29%)
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述

在这里插入图片描述


3、打包 Dex 文件


打包 Dex 文件 :

首先配置下环境变量 , 将编译工具目录配置到环境变量中 , 这里选择使用 30.0.3 版本的编译工具 ( build-tools ) ;

D:\001_Develop\001_SDK\Sdk\build-tools\30.0.3
  • 1

在这里插入图片描述

配置到环境变量 Path 中 ;

在这里插入图片描述

执行

dx --dex --output main.dex main.jar
  • 1

命令 , 打包 Dex 文件 , 命令行输出 :

在这里插入图片描述

打包后的 main.dex 文件 ;

在这里插入图片描述





二、反编译 Dex 文件



使用如下命令 , 反编译 Dex 文件 :

dexdump -d -l plain main.dex
  • 1

输出 Dex 文件的内容 :

D:\002_Project\004_Java_Learn\Main\out\production\Main>dexdump -d -l plain main.dex
Processing 'main.dex'...
Opened 'main.dex', DEX version '035'
Class #0            -
  Class descriptor  : 'LStudent;'
  Access flags      : 0x0001 (PUBLIC)
  Superclass        : 'Ljava/lang/Object;'
  Interfaces        -
  Static fields     -
  Instance fields   -
    #0              : (in LStudent;)
      name          : 'age'
      type          : 'I'
      access        : 0x0002 (PRIVATE)
    #1              : (in LStudent;)
      name          : 'name'
      type          : 'Ljava/lang/String;'
      access        : 0x0002 (PRIVATE)
  Direct methods    -
    #0              : (in LStudent;)
      name          : '<init>'
      type          : '()V'
      access        : 0x10001 (PUBLIC CONSTRUCTOR)
      code          -
      registers     : 1
      ins           : 1
      outs          : 1
      insns size    : 4 16-bit code units
0001b8:                                        |[0001b8] Student.<init>:()V
0001c8: 7010 0800 0000                         |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@0008
0001ce: 0e00                                   |0003: return-void
      catches       : (none)
      positions     :
        0x0000 line=1
      locals        :
        0x0000 - 0x0004 reg=0 this LStudent;

  Virtual methods   -
    #0              : (in LStudent;)
      name          : 'ageIncrease'
      type          : '()V'
      access        : 0x0001 (PUBLIC)
      code          -
      registers     : 2
      ins           : 1
      outs          : 0
      insns size    : 12 16-bit code units
0001d0:                                        |[0001d0] Student.ageIncrease:()V
0001e0: 1d01                                   |0000: monitor-enter v1
0001e2: 5210 0000                              |0001: iget v0, v1, LStudent;.age:I // field@0000
0001e6: d800 0001                              |0003: add-int/lit8 v0, v0, #int 1 // #01
0001ea: 5910 0000                              |0005: iput v0, v1, LStudent;.age:I // field@0000
0001ee: 1e01                                   |0007: monitor-exit v1
0001f0: 0e00                                   |0008: return-void
0001f2: 0d00                                   |0009: move-exception v0
0001f4: 1e01                                   |000a: monitor-exit v1
0001f6: 2700                                   |000b: throw v0
      catches       : 1
        0x0001 - 0x000b
          <any> -> 0x0009
      positions     :
        0x0000 line=22
        0x0001 line=23
        0x0007 line=24
        0x0008 line=25
        0x0009 line=24
      locals        :
        0x0000 - 0x000c reg=1 this LStudent;

    #1              : (in LStudent;)
      name          : 'getAge'
      type          : '()I'
      access        : 0x0001 (PUBLIC)
      code          -
      registers     : 2
      ins           : 1
      outs          : 0
      insns size    : 3 16-bit code units
000204:                                        |[000204] Student.getAge:()I
000214: 5210 0000                              |0000: iget v0, v1, LStudent;.age:I // field@0000
000218: 0f00                                   |0002: return v0
      catches       : (none)
      positions     :
        0x0000 line=14
      locals        :
        0x0000 - 0x0003 reg=1 this LStudent;

    #2              : (in LStudent;)
      name          : 'getName'
      type          : '()Ljava/lang/String;'
      access        : 0x0001 (PUBLIC)
      code          -
      registers     : 2
      ins           : 1
      outs          : 0
      insns size    : 3 16-bit code units
00021c:                                        |[00021c] Student.getName:()Ljava/lang/String;
00022c: 5410 0100                              |0000: iget-object v0, v1, LStudent;.name:Ljava/lang/String; // field@0001
000230: 1100                                   |0002: return-object v0
      catches       : (none)
      positions     :
        0x0000 line=6
      locals        :
        0x0000 - 0x0003 reg=1 this LStudent;

    #3              : (in LStudent;)
      name          : 'setAge'
      type          : '(I)V'
      access        : 0x0001 (PUBLIC)
      code          -
      registers     : 2
      ins           : 2
      outs          : 0
      insns size    : 3 16-bit code units
000234:                                        |[000234] Student.setAge:(I)V
000244: 5901 0000                              |0000: iput v1, v0, LStudent;.age:I // field@0000
000248: 0e00                                   |0002: return-void
      catches       : (none)
      positions     :
        0x0000 line=18
        0x0002 line=19
      locals        :
        0x0000 - 0x0003 reg=0 this LStudent;
        0x0000 - 0x0003 reg=1 age I

    #4              : (in LStudent;)
      name          : 'setName'
      type          : '(Ljava/lang/String;)V'
      access        : 0x0001 (PUBLIC)
      code          -
      registers     : 2
      ins           : 2
      outs          : 0
      insns size    : 3 16-bit code units
00024c:                                        |[00024c] Student.setName:(Ljava/lang/String;)V
00025c: 5b01 0100                              |0000: iput-object v1, v0, LStudent;.name:Ljava/lang/String; // field@0001
000260: 0e00                                   |0002: return-void
      catches       : (none)
      positions     :
        0x0000 line=10
        0x0002 line=11
      locals        :
        0x0000 - 0x0003 reg=0 this LStudent;
        0x0000 - 0x0003 reg=1 name Ljava/lang/String;

  source_file_idx   : 7 (Student.java)

Class #1            -
  Class descriptor  : 'LUser;'
  Access flags      : 0x0001 (PUBLIC)
  Superclass        : 'Ljava/lang/Object;'
  Interfaces        -
  Static fields     -
  Instance fields   -
    #0              : (in LUser;)
      name          : 'age'
      type          : 'I'
      access        : 0x0002 (PRIVATE)
  Direct methods    -
    #0              : (in LUser;)
      name          : '<init>'
      type          : '()V'
      access        : 0x10001 (PUBLIC CONSTRUCTOR)
      code          -
      registers     : 2
      ins           : 1
      outs          : 1
      insns size    : 7 16-bit code units
000264:                                        |[000264] User.<init>:()V
000274: 7010 0800 0100                         |0000: invoke-direct {v1}, Ljava/lang/Object;.<init>:()V // method@0008
00027a: 1200                                   |0003: const/4 v0, #int 0 // #0
00027c: 5910 0200                              |0004: iput v0, v1, LUser;.age:I // field@0002
000280: 0e00                                   |0006: return-void
      catches       : (none)
      positions     :
        0x0000 line=1
        0x0003 line=2
      locals        :
        0x0000 - 0x0007 reg=1 this LUser;

  Virtual methods   -
    #0              : (in LUser;)
      name          : 'increase'
      type          : '()V'
      access        : 0x20001 (PUBLIC DECLARED_SYNCHRONIZED)
      code          -
      registers     : 2
      ins           : 1
      outs          : 0
      insns size    : 12 16-bit code units
000284:                                        |[000284] User.increase:()V
000294: 1d01                                   |0000: monitor-enter v1
000296: 5210 0200                              |0001: iget v0, v1, LUser;.age:I // field@0002
00029a: d800 0001                              |0003: add-int/lit8 v0, v0, #int 1 // #01
00029e: 5910 0200                              |0005: iput v0, v1, LUser;.age:I // field@0002
0002a2: 1e01                                   |0007: monitor-exit v1
0002a4: 0e00                                   |0008: return-void
0002a6: 0d00                                   |0009: move-exception v0
0002a8: 1e01                                   |000a: monitor-exit v1
0002aa: 2700                                   |000b: throw v0
      catches       : 1
        0x0001 - 0x0007
          <any> -> 0x0009
      positions     :
        0x0000 line=5
        0x0007 line=6
        0x0009 line=5
      locals        :
        0x0000 - 0x000c reg=1 this LUser;

  source_file_idx   : 8 (User.java)


D:\002_Project\004_Java_Learn\Main\out\production\Main>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214

在这里插入图片描述





三、分析 Dex 文件




1、Student 类相关信息


#0 号 Class 类 , 类描述符是 LStudent; , 父类 Ljava/lang/Object;

Processing 'main.dex'...
Opened 'main.dex', DEX version '035'
Class #0            -
  Class descriptor  : 'LStudent;'
  Access flags      : 0x0001 (PUBLIC)
  Superclass        : 'Ljava/lang/Object;'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

该类中有 2 2 2 个字段 , 分别是 name 和 age ;

  Instance fields   -
    #0              : (in LStudent;)
      name          : 'age'
      type          : 'I'
      access        : 0x0002 (PRIVATE)
    #1              : (in LStudent;)
      name          : 'name'
      type          : 'Ljava/lang/String;'
      access        : 0x0002 (PRIVATE)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

构造函数方法 :

  Direct methods    -
    #0              : (in LStudent;)
      name          : '<init>'
      type          : '()V'
      access        : 0x10001 (PUBLIC CONSTRUCTOR)
      code          -
      registers     : 1
      ins           : 1
      outs          : 1
      insns size    : 4 16-bit code units
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

增加年龄方法 :

    public void ageIncrease(){
        synchronized(this) {
            this.age++;
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5

对应

  Virtual methods   -
    #0              : (in LStudent;)
      name          : 'ageIncrease'
      type          : '()V'
      access        : 0x0001 (PUBLIC)
      code          -
      registers     : 2
      ins           : 1
      outs          : 0
      insns size    : 12 16-bit code units
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

其它方法省略 ;


2、User 类相关信息


2 2 2 个类 编号 #1 , 是 User 类 , 类描述符 LUser; , 有 age 字段 ;

Class #1            -
  Class descriptor  : 'LUser;'
  Access flags      : 0x0001 (PUBLIC)
  Superclass        : 'Ljava/lang/Object;'
  Interfaces        -
  Static fields     -
  Instance fields   -
    #0              : (in LUser;)
      name          : 'age'
      type          : 'I'
      access        : 0x0002 (PRIVATE)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

构造方法反编译内容如下 :

  Direct methods    -
    #0              : (in LUser;)
      name          : '<init>'
      type          : '()V'
      access        : 0x10001 (PUBLIC CONSTRUCTOR)
      code          -
      registers     : 2
      ins           : 1
      outs          : 1
      insns size    : 7 16-bit code units
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

void increase() 方法对应反编译内容 :

  Virtual methods   -
    #0              : (in LUser;)
      name          : 'increase'
      type          : '()V'
      access        : 0x20001 (PUBLIC DECLARED_SYNCHRONIZED)
      code          -
      registers     : 2
      ins           : 1
      outs          : 0
      insns size    : 12 16-bit code units
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/789734
推荐阅读
相关标签
  

闽ICP备14008679号