描述符和数据类型
Smali数据类型,基本类型和引用类型.对象和数组都是引用类型
Java类型 | Smali类型描述符 |
---|---|
int | I |
long | J |
double | D |
boolean | Z |
float | F |
short | S |
char | C |
byte | B |
void | V |
对象类型 | L |
数组类型 | [ |
下面我们来看下这三种类型的代码
基本类型
Java1
2
3
4// 由于有9个基本类型,这里我只写出两个int和void
private int a = 1;
// 变量是没有void类型的,所以用方法表示
private void getVoid(String a, int b){}
Smali1
2
3
4
5
6
7
8
9
10
11
12
13
14
# instance fields
.field private a:I
# 先不看方法里面的内容,后面会说
.method private getVoid(Ljava/lang/String;I)V
.registers 3
.param p1, "a" # Ljava/lang/String;
.param p2, "b" # I
.prologue
.line 4
return-void
.end method
.field
表示一个字段,紧跟着private
表示该字段的可见性,然后a
表示字段名,I
表示字段类型为int
,中间用:
隔开。
.method
表示一个方法,private
同样是可见性,getVoid(Ljava/lang/String;I)
表示方法名为getVoid
,参数为Ljava/lang/String;
和I
类型,Ljava/lang/String;
为对象类型,以L
开头,;
结尾,后面的V
表示返回值为void
。
对象类型
Java1
2
3private String a;
private static String b;
private OtherClass c;
Smali1
2
3
4
5
6
7
8# static fields
.field private static b:Ljava/lang/String;
# instance fields
.field private a:Ljava/lang/String;
.field private c:Lcom/example/test/OtherClass;
L即上面定义的java类类型,表示后面跟着的是类的全限定名.比如java中的java.lang.String
对应的描述是Ljava/lang/String;
注意:全限定名就是,一个类的完整类名如String的完整类名是java.lang.String,并将里面的
.
替换成/
,然后在末尾加上;
结尾,这样的就叫全限定名。
数组类型
Java1
2private int[] a = new int[1];
private String[] b = new String[1];
Smali1
2
3
4# instance fields
.field private a:[I
.field private b:[Ljava/lang/String;
[表示数组类型,后面跟着基本类型或者对象类型,一维数组用一个[,二维数组用两个[表示,如int[][]
对应的描述就是[[I
,而对象类型数组,则是后面加上类的全限定名,如String[][]
对应的是[[Ljava/lang/String;
指令
Java对应Smali描述使用指令来完成的,下面我们来一一说明指令的作用。
文件头
我们在创建一个类的时候,会有包名,会有类名,类会继承父类,这就是文件头内容。
Java1
2
3
4package com.example.test;
public final class TestClass extends OtherClass {
}
Smali1
2
3.class public final Lcom/example/test/TestClass;
.super Lcom/example/test/OtherClass;
.source "TestClass.java"
这三行是每个文件的前三行,一定会有的。.class
声明该类的全限定名,声明了该类的可见性(访问权限),声明了该类为final(非权限修饰符),格式为:1
2
3.class <访问权限修饰符> [非权限修饰符] <类名>
# 访问权限修饰符即public, protected, private和default.
# 非权限修饰符则指的是final, abstract.
.super
表示声明该类的父类,默认父类为Ljava/lang/Object;
,格式为1
.super <父类名>
.source
表示声明该类的源文件名称,这里就是TestClass.java
1
.source <源文件名称>
文件内容
讲了文件头之后,接下来的就是文件正文了,也就是类的主体部分,主体内容大致包括接口描述、注解描述、字段描述、方法描述四个部分。
接口描述
在写一个类的时候,有时候会实现一个接口,我们来看看是转换的内容1
2
3
4package com.example.test;
public class TestClass implements OtherInterface, OtherClass {
}
Smali1
2
3
4
5
6
7.class public Lcom/example/test/TestClass;
.super Ljava/lang/Object;
.source "TestClass.java"
# interfaces
.implements Lcom/example/test/OtherInterface;
.implements Lcom/example/test/OtherClass;
.implements
就表示实现的接口描述,后面只能描述一个接口,多个接口用多个.implements
描述。
注解描述
1 | package com.example.test; |
Smali1
2
3
4
5
6
7
8
9
10
11# virtual methods
.method public annotationFun()V
.registers 1
# 这里就是注解了
.annotation runtime Lorg/junit/Test;
.end annotation
.prologue
.line 10
return-void
.end method
字段描述
1 | private final String fieldOne = "123"; |
Smali1
2
3
4
5
6# static fields
.field private static fieldTwo:Ljava/lang/String;
# instance fields
.field private final fieldOne:Ljava/lang/String;
方法描述
1 | package com.example.test; |
Smali1
2
3
4
5
6
7
8# virtual methods
.method public annotationFun()V
.registers 1
.prologue
.line 7
return-void
.end method