首页
社区
课程
招聘
[原创]让人纠结的finally
发表于: 2014-7-5 17:38 5664

[原创]让人纠结的finally

2014-7-5 17:38
5664
最近分析某一apk,被其中的各种try-catch-finally块虐得死去活来,有木有。。。
由于喜欢刨根,各种谷歌都没有给出解释。 一番研究之后,发现确实有些蹊跷。(本人水平有限,不喜勿喷,谢谢)

切入正题:
try{}catch反编译后,格式:   
    eg: .catch Ljava/io/FileNotFoundException; {:try_start_0 .. :try_end_0} :catch_0
加上finally,那就多一行声明:
   eg: .catchall {:try_start_0 .. :try_end_0} :catchall_0
大家都知道,finally块中的代码始终都要执行,那么是不是类似goto到finally块中去执行代码呢? 可惜不是,是直接复制了3份。
比如:
        try {
                FileInputStream stream = new FileInputStream(new File("/mnt/sdcard/test.txt"));
        } catch (FileNotFoundException e) {
                e.printStackTrace();
        }finally{
                System.out.println("Fin");
        }
smali:
:try_start_0
    new-instance v1, Ljava/io/FileInputStream;

    new-instance v2, Ljava/io/File;

    const-string v3, "/mnt/sdcard/test.txt"

    invoke-direct {v2, v3}, Ljava/io/File;-><init>(Ljava/lang/String;)V

    invoke-direct {v1, v2}, Ljava/io/FileInputStream;-><init>(Ljava/io/File;)V
    :try_end_0
    .catchall {:try_start_0 .. :try_end_0} :catchall_0
    .catch Ljava/io/FileNotFoundException; {:try_start_0 .. :try_end_0} :catch_0

    .line 28
    sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;

    const-string v2, "Fin"

    invoke-virtual {v1, v2}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V


    .line 30
    :goto_0
    return-void

    .line 24
    :catch_0
    move-exception v0

    .line 26
    .local v0, e:Ljava/io/FileNotFoundException;
    :try_start_1
    invoke-virtual {v0}, Ljava/io/FileNotFoundException;->printStackTrace()V
    :try_end_1
    .catchall {:try_start_1 .. :try_end_1} :catchall_0

    .line 28
    sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;

    const-string v2, "Fin"

    invoke-virtual {v1, v2}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V

    goto :goto_0

    .line 27
    .end local v0           #e:Ljava/io/FileNotFoundException;

    :catchall_0
    move-exception v1

    .line 28
    sget-object v2, Ljava/lang/System;->out:Ljava/io/PrintStream;

    const-string v3, "Fin"

    invoke-virtual {v2, v3}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V

    .line 29
    throw v1

(由于黄色看不清,这里修改为红色)

不难发现,正常执行流程和catch块中增加了finally中的代码,而且二者是同一个出口。(goto_0)
那黄色(第三块红色)那块是什么???
经过多次测试,只要catch块中调用了函数,就会隐式生成一个try,且只有.catchall
:try_start_1
    invoke-virtual {v0}, Ljava/io/FileNotFoundException;->printStackTrace()V
:try_end_1
.catchall {:try_start_1 .. :try_end_1} :catchall_0

catchall_n一般结构是:
move-exception vm
......
throw vm

另外,经过多次动态调试smali,都没有出现程序进入.catchall_n模块。估计是没有构造出相应的触发条件。由于运行时异常不需要显式声明,猜测可能运行时异常触发。故构造一下代码:
        public void fun(int flag) throws IllegalArgumentException
        {
                switch(flag){
                        case 1: throw new IllegalArgumentException();
                        case 2: throw new RuntimeException();
                        default: break;
                }
        }
        public void Test(int flag)
        {
                try {
                        fun(flag);               
                        foo();
                } catch (Exception e) {
                        foo();
                }finally{
                        Log.i("Finally", "Exit");
                }
        }
        public void foo(){
                throw new RuntimeException();
        }
由于Log.i("Finally", "Exit");会被拷贝三份,故修改.catall中的输出,进行区别。具体如下:
    :catchall_1a
    move-exception v1

    .line 39
    const-string v2, "Finally"

    const-string v3, "Exit_Finally"
修改"Exit"为"Exit_Finally"

    invoke-static {v2, v3}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

    .line 40
    throw v1
onCreate分别测试调用Test(0)和Test(1),均打印出"Exit_Finally",并未打印出"Exit"。


这下终于明白了.catchall的作用,确实保证了finally块中的代码一定会被执行。

PS:要是多重try-catch-finally嵌套,而且finally块中有很多代码,那就。。。 万恶的finally块,虐了我千百遍。。。

[峰会]看雪.第八届安全开发者峰会10月23日上海龙之梦大酒店举办!

上传的附件:
  • 1.png (11.44kb,17次下载)
收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 25
活跃值: (46)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
lz研究的真挺仔细
2014-7-7 09:38
0
雪    币: 9
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
   顶,分析的透彻。。。虽然从来不用finnally...这东西还是少用点好
2014-7-16 14:47
0
游客
登录 | 注册 方可回帖
返回
//