本文环境
java version "1.7.0_75"
dx version 1.11
baksmali 2.1.0
知识预备
系统注解
系统注解用来表示java反射相关的信息,是由编译器生成的。
存在于 .dex 文件annotation部分,只在运行时系统可见。
源码在 /libcore/dalvik/src/main/java/dalvik/annotation/ 目录下.
AnnotationDefault
注解类的默认注解类,如果指定了默认值,此注解类就会出现。
EnclosingClass
出现在内部类中,指定该 内部类/匿名内部类 所在的最近的外部类,此注解类必须和InnerClass注解类一同出现,不能和EnclosingMethod一同出现。
EnclosingMethod
出现在内部类中,指定该内部类所在的最近的外部函数,此注解类必须和InnerClass注解类一同出现,不能和EnclosingClass一同出现。
InnerClass
出现在内部类中,提供内部类的名字(不包括包名,匿名内部类值为null)和访问权限(同类的访问权限)。
该注解类需和EnclosingMethod或EnclosingClass之一一同出现。
MemberClasses
出现在具有内部类的类中,提供直接内部类(不包含嵌套)的类名列表。
Signature
出现由更复杂的类型定义的类、字段或者方法中,dex文件不定义signature的格式,此注解类只是指定源语言能够实现其语义
的相应的signature。
因此,signature并不能被解析或这验证,只能被高一级的API或者工具(如调试器)接管。
signature以字符串数组的形式存在,使用的时候拼接。只有编译工具才能将一个完整的signature分成几个字符串。
Throws
以数组形式指定某个方法抛出的异常类型。
内部类
java 在编译的时候会为每个类生成一个class文件,内部类的格式为 [外部类]$[内部类].class
.
java 代码
1 2 3 4 5 6 7 8 9 10
| class HeyInnerclass { class Inner1{ class Inner1_1{} } class Inner2{} private void func(){ class InnerFun{} } }
|
smali 代码
以下仅为部分相关代码。
HeyInnerclass
1 2 3 4 5 6 7 8 9 10 11 12 13
| # annotations //注解类MemberClasses .annotation system Ldalvik/annotation/MemberClasses; value = { LHeyInnerclass$Inner2;, LHeyInnerclass$Inner1; } .end annotation .method private func()V .registers 1 .prologue .line 18 return-void .end method
|
HeyInnerclass 中有 HeyInnerclass$Inner2 和 HeyInnerclass$Inner1 两个类!
func 方法中并没有任何实现还是占用了一个寄存器,这个寄存器表示自身(this)的引用。
Inner1
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
| # annotations //注解类 EnclosingClass .annotation system Ldalvik/annotation/EnclosingClass; value = LHeyInnerclass; .end annotation //注解类 InnerClass .annotation system Ldalvik/annotation/InnerClass; accessFlags = 0x0 name = "Inner1" .end annotation //注解类 MemberClasses .annotation system Ldalvik/annotation/MemberClasses; value = { LHeyInnerclass$Inner1$Inner1_1; } .end annotation # instance fields //声明字段this$0 .field final synthetic this$0:LHeyInnerclass; # direct methods .method constructor <init>(LHeyInnerclass;)V .registers 2 .prologue .line 3 //初始化字段 this$0 iput-object p1, p0, LHeyInnerclass$Inner1;->this$0:LHeyInnerclass; invoke-direct {p0}, Ljava/lang/Object;-><init>()V .line 5 return-void .end method
|
Inner1 中有一个内部类 HeyInnerclass$Inner1$Inner1_1,所在的外部类是 HeyInnerclass,名字是 Inner1,访问权限 0x0.
this$0
是 HeyInnerclass 类型的,是内部类的保留的对所在的外部类的引用,this表示父类的引用,0表示引用的层数。
synthetic
表示这是合成的,由编译器生成的,不是写出来的。
Inner2 与 Inner1 除了没有字节的内部类外其余基本一致,代码就不贴了。
Inner1_1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| # annotations #注解类 .annotation system Ldalvik/annotation/EnclosingClass; value = LHeyInnerclass$Inner1; .end annotation .annotation system Ldalvik/annotation/InnerClass; #注解类 accessFlags = 0x0 name = "Inner1_1" .end annotation # instance fields .field final synthetic this$1:LHeyInnerclass$Inner1; # direct methods .method constructor <init>(LHeyInnerclass$Inner1;)V .registers 2 .prologue .line 5 iput-object p1, p0, LHeyInnerclass$Inner1$Inner1_1;->this$1:LHeyInnerclass$Inner1; invoke-direct {p0}, Ljava/lang/Object;-><init>()V return-void .end method
|
Inner1_1 名字是 Inner1_1,访问权限为0x0,所在的外部类是HeyInnerclass$Inner1,
对外部类的的引用是 this$1,类型是 HeyInnerclass$Inner1,1表示引用层数深了一层。
InnerFun
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| # annotations #注解类 .annotation system Ldalvik/annotation/EnclosingMethod; value = LHeyInnerclass;->func()V .end annotation .annotation system Ldalvik/annotation/InnerClass; #注解类 accessFlags = 0x0 name = "InnerFun" .end annotation # instance fields #引用字段 .field final synthetic this$0:LHeyInnerclass; # direct methods .method constructor <init>(LHeyInnerclass;)V .registers 2 .prologue .line 17 iput-object p1, p0, LHeyInnerclass$1InnerFun;->this$0:LHeyInnerclass; invoke-direct {p0}, Ljava/lang/Object;-><init>()V return-void .end method
|
InnerFun的名字是InnerFun,访问权限是0x0,所在的方法是 LHeyInnerclass;->func()V .
对外部类的引用是 this$0,类型是 HeyInnerclass,引用层数为0.