Java Language Lambdas and memory utilization


Since Java lambdas are closures, they can "capture" the values of variables in the enclosing lexical scope. While not all lambdas capture anything -- simple lambdas like s -> s.length() capture nothing and are called stateless -- capturing lambdas require a temporary object to hold the captured variables. In this code snippet, the lambda () -> j is a capturing lambda, and may cause an object to be allocated when it is evaluated:

public static void main(String[] args) throws Exception {
    for (int i = 0; i < 1000000000; i++) {
        int j = i;
        doSomethingWithLambda(() -> j);

Although it might not be immediately obvious since the new keyword doesn't appear anywhere in the snippet, this code is liable to create 1,000,000,000 separate objects to represent the instances of the () -> j lambda expression. However, it should also be noted that future versions of Java1 may be able to optimize this so that at runtime the lambda instances were reused, or were represented in some other way.

1 - For instance, Java 9 introduces an optional "link" phase to the Java build sequence which will provide the opportunity for doing global optimizations like this.