MainActivity$1.smali和匿名内部类

MainActivity$1.smali

在android逆向中我们经常遇到xxx.smali和xxx$1.smali这种一起出现,这是什么意思呢?

我用jadx反编译并导出gradle工程看看。
jadx -e AliCrackme_2.apk,得到文件如下,观察MainActivity.java

用apktools反编译并用jd-gui打开

这样一对比就很清楚了,反编译出来的MainActivity$1,实际上是MainActivity的匿名内部类。

匿名内部类

语法

定义一个匿名内部类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Out {
private static int a;
private int b;

private Object obj = new Object() {
private String name = "匿名内部类";
@Override
public String toString() {
return name;
}
};

public void test() {
Object obj = new Object() {
@Override
public String toString() {
System.out.println(b);
return String.valueOf(a);
}
};
System.out.println(obj.toString());
}
}

匿名内部类可以出现在任何允许表达式出现的地方,定义格式:

1
2
3
new 类/接口{ 
//匿名内部类实现部分
}

实现原理

Out.java编译后匿名内部类会生成相应的class文件

1
2
3
4
5
6
7
8
9
10
11
12
class Out$1 {
private String name;

Out$1(Out var1) {
this.this$0 = var1;
this.name = "匿名内部类";
}

public String toString() {
return this.name;
}
}

匿名内部类可以访问外部类所有的变量和方法。

应用场景

匿名内部类使用广泛,比如我们常用的绑定监听的时候。

1
2
3
4
5
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(v.getContext(),"click",Toast.LENGTH_SHORT).show(); }
});

总结

所以逆向的时候不必过于关注xxx$数字这样的文件。