包含lambda表达式的代码是否会在较旧的JVM上运行,例如,对于java 1.6?

Lambda是在Java8中引入的。 包含lambda表达式的代码是否会在较旧的JVM上运行,例如,对于java 1.6? 我担心二进制兼容性而不是源代码兼容性。 这是一个简单的是/否问题。

谢谢。

Oracle非常努力地将Java语言和JVM字节码语言分开。 Java语言规范只说明包含lambda表达式的程序意味着什么 ,它没有说明如何编译或解释该程序 。

这意味着Java语言规范中没有任何内容禁止lambda表达式以这样的方式编译,即生成的代码可以由Java 6 JVM执行,但Java语言规范中没有任何内容可以保证它。 允许每个Java供应商以他们想要的任何方式编码lambda表达式。 (显然,出于实际的原因,大多数尝试匹配Oracle所做的非常紧密的事情。例如,可以理解和反向工程由Oracle的javac编码的lambdas的调试器/反编译器/工具将自动使用IBM生成的字节码J9 JDK的Java编译器。)

随Oracle JDK一起提供的javac编译器使用LambdaMetafactoryMethodHandleinvokedynamic相当复杂的机制对lambda表达式进行编码。 后者仅在Java 7 JVM中 引入 ,因此这意味着Oracles JDK的javac使用的特定编码至少需要Java 7 JVM。 但其他编码绝对是可能的,这些复杂的机器都不是真正必要的,它只是一种性能优化。 你可以将Lambda Expressions编码为内部类 ,这可以归结为Java 1.1 JVM – 这毕竟是我们编写的“穷人的lambdas”到Java 8的结果。 这也是lambda的原始提议甚至Java 8的早期预览如何实现它,毕竟,Java中lambda的开发甚至是Java 7和invokedynamic

有一个名为RetroLambda的编译器,它将Oracle JDK javac生成的Java 8 JVM字节码(不是J​​ava源代码!) javac为Java 7 JVM字节码,Java 6 JVM字节码或Java 5 JVM字节码。 使用此编译器,您可以生成包含字节码的类文件,该文件代码将在Java 8源代码上运行在任何Java 5或更高版本的JVM上,该源代码使用( 几乎 )Java 8的所有function。

简短的回答:这取决于。

如果您完全受限于Oracle javac和库,答案是:no; 由于以下原因。

Java字节码包含主要版本号。 默认情况下,Java 8编译器将java8放入数据中。 任何较旧的JVM都拒绝运行该代码。 虽然可以告诉Java 8编译器创建与旧JVM兼容的字节码。 但是:为了让旧的JVM执行这样的“特殊”类文件,您需要所有的依赖项都可用!

并且它中断了:Lambdas使用了Java 6中不存在的invokedynamic字节码指令。除此之外,编译器在编译lambdas时使用了大量的Java库 – 所有这些都在java 6之后添加。

因此,即使您设法使用源代码将lambda编译为Java 6字节码 – 该指令也不可用,并且您还需要提供所有其他类。

但是:正如另一个伟大的答案所解释的那样,javac还有其他选择,允许你在旧的JVM上使用lambdas。

但是:小心如何消耗能量。 Java 6对于“服务器端java”仍然是死的。 因此,对于像Android这样的平台,使用这些替代方案是可以的,但是当您仍在某处运行Oracle Java 6 JVM时,您应该将精力用于将该系统升级到当前版本的Java。

正如其他人所说:不

javac编译器生成的类文件是版本化的。 Java 8生成的所有内容都标记为默认需要Java 8 JVM。 较旧版本的JVM不接受二进制文件。

如果你想为旧平台编译,你必须告诉javac: javac -target 6 。 只要将此选项添加到命令行,Java 8编译器就会要求您指定-source 6 (或更低)。 因此,它不会接受任何包含lambda表达式的代码。