Retrolambda lets you run Java 8 code with lambda expressions, method references and try-with-resources statements on Java 7, 6 or 5. It does this by transforming your Java 8 compiled bytecode so that it can run on an older Java runtime.
Backported Language Features:
Lambda expressions are backported by converting them to anonymous inner classes. This includes the optimisation of using a singleton instance for stateless lambda expressions to avoid repeated object allocation. Method references are basically just syntax sugar for lambda expressions and they are backported in the same way.
Try-with-resources statements are backported by removing calls to Throwable.addSuppressed
if the target bytecode version is below Java 7. If you would like the suppressed exceptions to be logged instead of swallowed, please create a feature request and we'll make it configurable.
Objects.requireNonNull
calls are replaced with calls to Object.getClass
if the target bytecode version is below Java 7. The synthetic null checks generated by JDK 9 use Objects.requireNonNull
, whereas earlier JDK versions used Object.getClass
.
Optionally also:
Default methods are backported by copying the default methods to a companion class (interface name + "$") as static methods, replacing the default methods in the interface with abstract methods, and by adding the necessary method implementations to all classes which implement that interface.
Static methods on interfaces are backported by moving the static methods to a companion class (interface name + "$"), and by changing all methods calls to call the new method location.
Known Limitations:
Does not backport Java 8 APIs
Backporting default methods and static methods on interfaces requires all backported interfaces and all classes which implement them or call their static methods to be backported together, with one execution of Retrolambda. In other words, you must always do a clean build. Also, backporting default methods won't work across module or dependency boundaries.
May break if a future JDK 8 build stops generating a new class for each invokedynamic
call. Retrolambda works so that it captures the bytecode that java.lang.invoke.LambdaMetafactory
generates dynamically, so optimisations to that mechanism may break Retrolambda.
Retrolambda gradle plugin will automatically build your android project with Retrolambda. The latest version can be found on the releases page.
Usage:
build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'me.tatarka:gradle-retrolambda:<latest version>'
}
}
// Required because retrolambda is on maven central
repositories {
mavenCentral()
}
apply plugin: 'com.android.application' //or apply plugin: 'java'
apply plugin: 'me.tatarka.retrolambda'
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
Known Issues:
Lint fails on java files that have lambdas. Android's lint doesn't understand java 8 syntax and will fail silently or loudly. There is now an experimental fork that fixes the issue.
Using Google Play Services causes Retrolambda to fail. Version 5.0.77 contains bytecode that is incompatible with Retrolambda. This should be fixed in newer versions of play services, if you can update, that should be the preferred solution. To work around this issue, you can either use an earlier version like 4.4.52 or add -noverify
to the jvm args.
retrolambda {
jvmArgs '-noverify'
}