Lambdas and instantiation

Alex Blewitt alex.blewitt at gmail.com
Thu Jan 28 17:45:46 PST 2010


I think it would be good to define in what circumstances a lambda can
result in a new instance created under the covers. If we don't mention
anything in the spec, then developers may (incorrectly) assume that no
instance-binding operator takes place. For example, JLS3 15.6 defines
"Normal and Abrupt Completion of Evaluation"

http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.6

"A class instance creation expression (§15.9), array creation
expression (§15.10), or string concatenation operator expression
(§15.18.1) throws an OutOfMemoryError if there is insufficient memory
available"

This can be seen to hold for lambda instantiation as well, though not
necessarily all the time. Consider:

int main(String args[]) {
  int big = ...;
  Object[] lambdas = new Object[big];
  for(final int i=0;i<big;i++)
    lambdas[i] = #int() { return i; }
}

For a suitably large value of 'big', this must run out of memory.
However, according to the JLS, the only place which might throw this
is the array assignment 'lambdas='.

However, I'd expect this not to run out of memory:

  lambdas[i] = #int() { return 42; }

since the compiler could re-write the lambda into (effectively) a
static final lambda whose instance then gets reused.

The distinction between the two is that one is a closure and one is
not. Arguably, non-closures should always result in a staticly
promotable reference since by definition, a non-closure doesn't
capture any local state. However, one could also argue that an
(effectively) final variable also consists of a staticly promotable
lambda:

final int fortyTwo = 42;
 lambdas[i] = #int() { return fortyTwo }; // a closure, but one that
the compiler could optimise out

In both the above cases, the compiler can re-write as:

Object[] lambdas[] = new Object[big]; // could throw OOME
#int() lambda = #int() { return 42; } // could throw OOME, but only once
for(final int i=0;i<big;i++)
  lambads[i] = lambda; // no longer throws an OOME

The spec may want to observe that the creation of a lambda may result
in an OOME but perhaps observe the behavioural differences between
capturing and non-capturing state.

Alex


More information about the lambda-dev mailing list