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