soot 静态分析框架(四)Soot lambda 构建

1. JVM 的 Lambda构建

和JVM构建Lambda的方式不同,因为Lambda表达式的类是一个运行的时候动态生成的类,是通过新的JVM的指令集InvokeDynamic来实现,通过调用java/lang/invoke/LambdaMetafactory.metafactory去生成动态的内部Class,在Class里面封装了实现的抽象方法,在抽象方法里实现了对源类的静态方法package.classname.lambda$0的调用,Lambda里的实现的逻辑就在package.classname.lambda$0里,生成的动态的class里直接调用原类的静态的私有方法 package.classname.lambda$0

关于JVM如何构建Lambda表达式具体细节可参考博客(https://blog.csdn.net/raintungli/article/details/54910152),本篇博客就不在阐述。

2. Soot Lambda构建

因为Soot是静态分析工具,对JVM运行时后生成的类不能等到JVM运行的时候生成后进行分析,只能先提前生成。

Soot自己也封装了LambdaMetaFactory中,首先生成一个内部类package.classname.$lambda_0__1实现了你的接口myinterface,里面分装了a.     bootstrap$()

public static myinterface bootstrap$()

    {

        package.classname$lambda_0__1 $r0;

 

        $r0 = new pointto.testContainer$lambda_0__1;

 

        specialinvoke $r0.< package.classname$lambda_0__1: void ()>();

 

        return $r0;

    }

 

初始化了类package.classname$lambda_0__1类,并返回

b.  init的方法

public void ()

    {

        pointto.testContainer$lambda_0__1 $r0;

 

        $r0 := @this: pointto.testContainer$lambda_0__1;

 

        specialinvoke $r0.()>();

 

        return;

    }

 

调用Object的init方法,所有类都继承object 需要在函数里调用object 的init方法

c.实现的接口的方法

 

public void method(java.lang.Object)

    {

        package.classname $lambda_0__1 $r0;

        java.lang.Object $r1;

        java.lang.String $r2;

 

        $r0 := @this: package.classname$lambda_0__1;

 

        $r1 := @parameter0: java.lang.Object;

 

        $r2 = (java.lang.String) $r1;

 

        staticinvoke ($r2);

 

        return;

    }

 

其本质和JVM一样就是调用package.classname.lambda$0的方法

 

这里和JVM不同的是,动态生成的类是在分析过程中直接虚拟生成的,和java的生成的类不同的是没有bootstrap$这个方法,调用方式也不一样

jvm是

 

0: invokedynamic #30,  0             // InvokeDynamic #0:accept:()Ljava/util/function/Consumer;

而soot里就是直接调用了 bootstrap$的方法

staticinvoke ();

 

个人觉的可以直接调用private static void lambda$0(java.lang.String);来构建call graph

你可能感兴趣的:(静态分析,Soot)