关于Java-8-Lambdas(By Richard Warburton Raoul-Gabriel Urma )

A 第一节

https://www.infoq.com/articles/Java-8-Lambdas-A-Peek-Under-the-Hood/

Java 8 was released in March 2014 and introduced lambda expressions as its flagship feature. You may already be using them in your code base to write more concise and flexible code. For example, you can combine lambda expressions with the new Streams API to express rich data processing queries:



Java8于2014年3月发布,并引入了lambda表达式作为其旗舰特性。您可能已经在代码库中使用它们来编写更简洁和灵活的代码。例如,可以将lambda表达式与新的Streams API结合起来,以表示丰富的数据处理查询:

然后紧接着往下看

匿名内部类具有可能影响应用程序性能的不良特性。

首先,编译器为每个匿名内部类生成一个新的类文件。文件名通常看起来像类名$1,其中ClassName是定义匿名内部类的类的名称,后跟一个美元符号和一个数字。生成许多类文件是不可取的,因为每个类文件在使用之前都需要加载和验证,这会影响应用程序的启动性能。加载可能是一个昂贵的操作,包括磁盘I/O和解压JAR文件本身。

如果lambda被转换为匿名内部类,那么每个lambda都会有一个新的类文件。当加载每个匿名内部类时,它将占用JVM的元空间(java8代替永久代)。如果JVM将每个匿名内部类中的代码编译为机器代码,那么它将存储在代码缓存中。此外,这些匿名内部类将被实例化为单独的对象。因此,匿名内部类会增加应用程序的内存消耗。为了减少所有这些内存开销,引入一种缓存机制可能会很有帮助,这促使引入某种抽象层。

最重要的是,从一开始就选择使用匿名内部类来实现lambda,这将限制lambda未来实现更改的范围,以及它们根据未来JVM改进而演进的能力。

作者举了一个例子

import java.util.function.Function;
public class AnonymousClassExample {
    Function<String, String> format = new Function<String, String>() {
        public String apply(String input){
            return Character.toUpperCase(input.charAt(0)) + input.substring(1);
        }
    };
}

You can examine the bytecode generated for any class file using the command
您可以使用命令检查为任何类文件生成的字节码

不妨看看生成后的字节码文件
发现

0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: new #2 // class AnonymousClassExample1 8: dup 9: aload_0 10: invokespecial #3 // Method AnonymousClass1."<init>":(LAnonymousClassExample;)V
13: putfield #4 // Field format:Ljava/util/function/Function;
16: return

翻译一下也就是说

5: 使用字节码操作new实例化AnonymousClassExample$1类型的对象。对新创建的对象的引用同时被推送到堆栈上。

8: 操作dup在堆栈上复制该引用。

10: 该值随后由invokespecial指令使用,该指令初始化匿名内部类实例。

13: 堆栈顶部现在仍然包含对对象的引用,该引用使用putfield指令存储在AnonymousClassExample类的format字段中

AnonymousClassExample1 是编译器为匿名内部类生成的名称。如果你想让自己安心,你也可以检查匿名类示例1类文件,你会找到实现函数接口的代码。

将lambda表达式转换为匿名内部类将限制未来可能的优化(例如缓存),因为它们将绑定到匿名内部类字节码生成机制。因此,语言和JVM工程师需要一个稳定的二进制表示法,该表示法能够提供足够的信息,同时允许JVM在未来使用其他可能的实现策略。下一节将解释如何做到这一点!**

B 第二节

为了解决上一节中解释的问题,Java语言和JVM工程师决定将转换策略的选择推迟到运行时。Java7引入的新invokedynamic字节码指令为他们提供了一种机制,可以有效地实现这一点。lambda表达式到字节码的转换分两步执行:

生成一个invokedynamic调用站点(称为lambda factory),当调用该站点时,将返回lambda正在转换到的函数接口的实例;

将lambda表达式的主体转换为将通过invokedynamic指令调用的方法。

为了演示第一步,让我们检查编译包含lambda表达式的简单类时生成的字节码,例如:

import java.util.function.Function;

public class Lambda {
    Function<String, Integer> f = s -> Integer.parseInt(s);
}
 0: aload_0
 1: invokespecial #1 // Method java/lang/Object."<init>":()V
 4: aload_0
 5: invokedynamic #2, 0 // InvokeDynamic
                  #0:apply:()Ljava/util/function/Function;
10: putfield #3 // Field f:Ljava/util/function/Function;
13: return

发现lambda表达式字节码是通过invokedynamic 指令在操作的,即运行时进行初始化

我们遇到这种情况不是通过寻找场景,而是通过内存分析,并且有一个很好的业务用例来证明优化的合理性。我们还处在这样一个位置,即只分配一次对象,它大量重用lambda表达式,因此缓存非常有益。与任何性能调整练习一样,科学方法是普遍推荐的方法。
这是任何其他想要优化lambda表达式使用的最终用户也应该采用的方法。尝试编写干净、简单和实用的代码总是最好的第一步。任何优化,如这次吊装,只应针对真正的问题进行。编写捕捉分配对象的lambda表达式并不是天生的坏事,就像编写调用“new Foo()”的Java代码一样,它本身也不是坏事。
这一经验也表明,要从lambda表达式中获得最佳效果,使用它们的习惯用法非常重要。如果lambda表达式用于表示小型的纯函数,则它们不需要从其周围的范围捕获任何内容。和大多数事情一样,如果你保持简单,事情就会表现得很简单

C思考

1.我有在博客上看到有人写实验,判别Lambdas 与for循环的性能的实验,得出的结论是Lambdas 性能不好,要比for循环慢。这种说法和做法是比较没有经验验证的,事实与结果证明,Lambdas 性能是比较理想的。

2.我们现在关注的点在于Lambdas 的使用习惯,他第一次使用的时候会很慢,是因为她的运行机制有关系,运行时加载。因为他要加载oracle的asm类。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342