java compile handle lambda steps:
1.把lambda body转为的一个实现方法,用methodhandle 表示这个方法
2.知道将要把lambda转成哪种function interface,comsumer 还是predict
3.获取其它元数据,例如序列化信息
4.将要传入lambda中的值
如下图,前三个是静态的,第4个是动态的
2.
上图中indy是invocatdynamic的缩写,bootstrap是一个lambda工厂,它决定最终怎样的策略生成lambda代码,Predicate是目标类型,lambda$1是方法,
以及参数minage.然后把它扔给list.removeif.整个过程的动态性,体现在lambda的最终代码(例如是内部类,还是其他策略)是在runtime生成的,从编译推迟到运行时,
多次调用时,第一次询问bootstrap以后,后面在类型不变的情况下,就不在询问bootstrap了。运行时,能够获得更多的信息,但是如果lambda仅仅是一个x->x*2这样
不用用到自身以外的其他信息,这在无状态无属性的lambda,会直接生成方法调用,不走class路线,sun公司
也会不断优化策略。例如专门给runnable和compartor指定一种类。
5.lambda的成本组成(最坏相当于内部类,最好相当于直接方法调用)
1)一次性成本-----link成本,class只需要load一次
2)每个lambda表达式成本---------capture cost, 对于有变化的X以外的变量,每变一次,要调用一次constructor,因为这个变量是innerclass的一个私有属性,用constructor给它赋值。生成instance,然后专心处理X变量。
3)调用lambda内部方法的成本,跟普通方法调用一样
上图saturated为80个服务器时,non-capturing lambda会比内部类性能高很多,所以简单的匿名内部类可以用method reference代替