【smali】一些smali不常见的语法

1.内部类:一个包含简单的匿名内部类的代码:
public class EventQs extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 获取应用程序中的bn按钮
Button bn = (Button) findViewById(R.id.bn);
// 为按钮绑定事件监听器。
bn.setOnClickListener(new MyClickListener()); // ①
}

// 定义一个单击事件的监听器
class MyClickListener implements View.OnClickListener
{
// 实现监听器类必须实现的方法,该方法将会作为事件处理器
@Override
public void onClick(View v)
{
EditText txt = (EditText) findViewById(R.id.txt);
txt.setText("bn按钮被单击了!");
}
}
}
在EventQs  的smali的代码中 会包含这样的注释:
# annotations
.annotation system Ldalvik/annotation/MemberClasses;
    value = {
        Lorg/crazyit/event/EventQs$MyClickListener;
    }
.end annotation
MemberClasses 为内部类,他代表这该类中内部类的列表,其中value中就包含了一个内部类MyClickListener
而内部类的反编译代码中包含的注释也说明自身是一个内部类。
EventQs$MyClickListener.smali:
# annotations
.annotation system Ldalvik/annotation/EnclosingClass;
    value = Lorg/crazyit/event/EventQs;
.end annotation

.annotation system Ldalvik/annotation/InnerClass;
    accessFlags = 0x0
    name = "MyClickListener"
.end annotation
EnclosingClass注解表明MainActivity$SNChecker作用于一个类,注解的value表明这个类是MainActivity。在EnclosingClass注解的下面是InnerClass,它表明自身是一个内部类,其中的accessFlags访问标志是一个枚举值



public class ViewSwitcherTest extends Activity
{
        public static class DataItem
         {
          // 应用程序名称
          public String dataName;
          // 应用程序图标
          public Drawable drawable;
         }

        ArrayList items = new ArrayList();
};
在ViewSwitcherTest 中内部类对应的代码 使用注释类来表达
# annotations
.annotation system Ldalvik/annotation/MemberClasses;
    value = {
        Lorg/crazyit/ui/ViewSwitcherTest$DataItem;
    }
.end annotation
MemberClasses注解是一个系统注解,作用是为父类提供一个内部类列表

而在ViewSwitcherTest$DataItem中自身的类申明为:
# annotations
.annotation system Ldalvik/annotation/EnclosingClass;
    value = Lorg/crazyit/ui/ViewSwitcherTest;
.end annotation
.annotation system Ldalvik/annotation/InnerClass;
    accessFlags = 0x9
    name = "DataItem"
.end annotation
EnclosingClas表示DataItem作用于ViewSwitcherTest。下面的InnerClass表明他是一个子类,该子类的名字为DataItem。



利用内部类 创建的ArrayList对象:ArrayList items = new ArrayList();

.field private items:Ljava/util/ArrayList;
    .annotation system Ldalvik/annotation/Signature;
        value = {
            "Ljava/util/ArrayList",
            "<",
            "Lorg/crazyit/ui/ViewSwitcherTest$DataItem;",
            ">;"
        }
    .end annotation
.end field



2.泛型
Class[] claszzs={PreferenceActivityTest.class,ExpandableListActivityTest.class};其代码为:实例字段,其中?变成了*
# instance fields
.field claszzs:[Ljava/lang/Class;
    .annotation system Ldalvik/annotation/Signature;
        value = {
            "[",
            "Ljava/lang/Class",
            "<*>;"
        }
    .end annotation
.end field

3. 判断是否为指定类的实例if (!(activity instanceof Callbacks))
其反编译代码:
instance-of v0, p1, Lcom/example/fargmenttest2/BookListFragment$Callbacks;
判断p1是否是其后的类的实例(也可以是接口)如果是返回非0值给v0 否则返回0

4.异常
throw new IllegalStateException("BookListFargment所在的activity必须实现callbacks接口!");
反编译代码:
    new-instance v0, Ljava/lang/IllegalStateException;
    const-string v1, "BookListFargment\u6240\u5728\u7684activity\u5fc5\u987b\u5b9e\u73b0callbacks\u63a5\u53e3\uff01"
    invoke-direct {v0, v1}, Ljava/lang/IllegalStateException;->(Ljava/lang/String;)V
    throw v0

5.返回值
protected ArrayList> converCurrsorTolist(Cursor cursor)
{
}

反编译代码:
.method protected converCurrsorTolist(Landroid/database/Cursor;)Ljava/util/ArrayList;
    .locals 4
    .parameter "cursor"
    .annotation system Ldalvik/annotation/Signature;
        value = {
            "(",
            "Landroid/database/Cursor;",
            ")",
            "Ljava/util/ArrayList",
            "<",
            "Ljava/util/Map",
            "<",
            "Ljava/lang/String;",
            "Ljava/lang/String;",
            ">;>;"
        }
    .end annotation
  .prologue
.end method

6.getMethod的 Class... parameterTypes参数
函数原型:public Method getMethod (String name, Class... parameterTypes)
parameterTypes参数实际上是Class []类型。
源代码如下:
  Method method = Class.forName( "android.os.ServiceManager").getMethod("getService", String.class);
反编译代码:
   const-string v4, "android.os.ServiceManager"
    .line 63
    invoke-static {v4}, Ljava/lang/Class;->forName(Ljava/lang/String;)Ljava/lang/Class;
    move-result-object v4
    .line 65
    const-string v5, "getService"
    const/4 v6, 0x1
    new-array v6, v6, [Ljava/lang/Class;
    const/4 v7, 0x0
    const-class v8, Ljava/lang/String;
    aput-object v8, v6, v7
@代码中是new Class[]{String.class},其效果等于源代码中的String.class
    .line 64
    invoke-virtual {v4, v5, v6}, Ljava/lang/Class;->getMethod(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
    move-result-object v2
    .line 67
    .local v2, method:Ljava/lang/reflect/Method;


7.静态方法中没有this指针,也就是p0不再是this指针,而是第一个参数

.method public static hookMethod(Ljava/lang/Class;Ljava/lang/reflect/Constructor;Lcom/saurik/substrate/MS$MethodAlteration;)V
    .locals 0
    .parameter "clazz"  //P0
    .parameter "member"   //P1
    .parameter   //P2
    .annotation system Ldalvik/annotation/Signature;
        value = {
            "             "Ljava/lang/Object;",
            "R:",
            "Ljava/lang/Object;",
            ">(",
            "Ljava/lang/Class;",
            "Ljava/lang/reflect/Constructor;",
            "Lcom/saurik/substrate/MS$MethodAlteration",
            ";)V"
        }
    .end annotation

    .prologue
    .line 112
    .local p2, alteration:Lcom/saurik/substrate/MS$MethodAlteration;,"Lcom/saurik/substrate/MS$MethodAlteration;"
    invoke-static {p0, p1, p2}, Lcom/saurik/substrate/MS;->hookMethod_(Ljava/lang/Class;Ljava/lang/reflect/Member;Lcom/saurik/substrate/MS$MethodAlteration;)V

    .line 113
    return-void
.end method
对应代码为:
public static void hookMethod(Class paramClass, Constructor paramConstructor, MethodAlteration paramMethodAlteration)
  {
    hookMethod_(paramClass, paramConstructor, paramMethodAlteration);
  }


8. finally语句块

finally 语句块作用:执行一些必要代码。即不管出现异常与否,在finally中的代码都会被执行
执行时机:针对所有catch语句之后,退出方法之前将被执行(即先执行catch里面的代码,但在throw之前将转向finally)。finally中返回的结果将可以覆盖catch中返回的结果
对应的smail代码如下: :try_start_0
    new-instance v2, Ljava/net/ServerSocket;

    const/16 v3, 0x2710

    invoke-direct {v2, v3}, Ljava/net/ServerSocket;->(I)V

    .line 21
    .local v2, serverSocket:Ljava/net/ServerSocket;
    invoke-virtual {v2}, Ljava/net/ServerSocket;->accept()Ljava/net/Socket;
    :try_end_0
    .catchall {:try_start_0 .. :try_end_0} :catchall_0  //处理start_0对应的异常块是catchall_0   也就是finally
    .catch Ljava/io/IOException; {:try_start_0 .. :try_end_0} :catch_0//处理start_0对应的异常块是catch_0,catch_0异常块先执行,之后再执行catchall_0  

源代码为:
try {
            ServerSocket serverSocket= new ServerSocket(10000);
            Socket socket=serverSocket.accept();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
        
                int abc=5;
                Toast.makeText(this, "sssss ", Toast.LENGTH_SHORT).show();
        
    }

想对应的代码为:
  const/4 v5, 0x0
    .line 17
    invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V
    .line 18
    const/high16 v3, 0x7f03
    invoke-virtual {p0, v3}, Lcom/example/finallytest/MainActivity;->setContentView(I)V
    .line 20
    :try_start_0
    new-instance v2, Ljava/net/ServerSocket;
    const/16 v3, 0x2710
    invoke-direct {v2, v3}, Ljava/net/ServerSocket;->(I)V
    .line 21
    .local v2, serverSocket:Ljava/net/ServerSocket;
    invoke-virtual {v2}, Ljava/net/ServerSocket;->accept()Ljava/net/Socket;
    :try_end_0
    .catchall {:try_start_0 .. :try_end_0} :catchall_0
    .catch Ljava/io/IOException; {:try_start_0 .. :try_end_0} :catch_0
    .line 27
    const/4 v0, 0x5
      @正常流程 即未发生异常
    .line 28
    .local v0, abc:I
    const-string v3, "sssss "
    invoke-static {p0, v3, v5}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
    move-result-object v3
    invoke-virtual {v3}, Landroid/widget/Toast;->show()V
    .line 32
    .end local v2           #serverSocket:Ljava/net/ServerSocket;
    :goto_0
    return-void
    .line 22
    .end local v0           #abc:I
    :catch_0
     @当发生异常时执行
    move-exception v1
    .line 24
    .local v1, e:Ljava/io/IOException;
    :try_start_1
    invoke-virtual {v1}, Ljava/io/IOException;->printStackTrace()V
    :try_end_1
    .catchall {:try_start_1 .. :try_end_1} :catchall_0
    @异常部分执行完毕,转而执行finally
    .line 27
    const/4 v0, 0x5
    .line 28
    .restart local v0       #abc:I
    const-string v3, "sssss "
    invoke-static {p0, v3, v5}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
    move-result-object v3
    invoke-virtual {v3}, Landroid/widget/Toast;->show()V
    goto :goto_0
    .line 25
    .end local v0           #abc:I
    .end local v1           #e:Ljava/io/IOException;
   
   @finally代码定义部分
    :catchall_0
    move-exception v3
    .line 27
    const/4 v0, 0x5
    .line 28
    .restart local v0       #abc:I
    const-string v4, "sssss "
    invoke-static {p0, v4, v5}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
    move-result-object v4
    invoke-virtual {v4}, Landroid/widget/Toast;->show()V
    .line 30
    throw v3

你可能感兴趣的:(Smail)