One final stab at improving lambda serialization

David M. Lloyd david.lloyd at
Tue Aug 27 15:21:06 PDT 2013

Just want to clarify that this correction applies to the background 
information regarding anonymous classes, *not* to the actual proposal 
itself (specifically the "The de-facto (and likely accidental) 
definition of "significant" used by inner classes here is:..." section 
under "User expectations").  I think I just about stopped Brian's heart. :-)

On 08/27/2013 04:01 PM, David M. Lloyd wrote:
> On 08/19/2013 10:37 AM, Brian Goetz wrote:
>  > [...]
>> The other failure has to do with order-of-capture.
>> *Old code**
>> *     *New code**
>> *     *Result**
>> *
>> String s1 = "foo";
>> String s2 = "bar";
>> Runnable r = new Runnable() {
>>      void run() {
>> foo(s1, s2);
>>      }
>> };
>>     String s1 = "foo";
>> String s2 = "bar";
>> Runnable r = new Runnable() {
>>      void run() {
>>          String s = s2;
>> foo(s1, s);
>>      }
>> };
>>     On deserialization, s1 and s2 are effectively swapped.
>> This fails because the order of arguments in the implicitly generated
>> constructor of the inner class changes due to the order in which the
>> compiler encounters captured variables.  If the reordered variables were
>> of different types, this would cause a type-1 failure, but if they are
>> the same type, it causes a type-2 failure.
> This appears to not strictly be accurate.  In my tests I've found that
> yes the constructor parameter ordering may indeed differ (based on this
> or (potentially) even any other compiler-specific factor), however since
> the constructor is not actually used during deserialize (the mandatory
> no-arg constructor of the first non-serializable superclass is used
> instead), this difference is irrelevant (to this particular problem).
> The serialization values are stored by field name in the serialization
> stream and filled in via reflection; every Java compiler I have access
> to names these fields e.g. "val$s1" and "val$s2" with the local variable
> name stored in the field name.  From my testing, this case seems like it
> would work "as expected" (and, given the apparent complete ubiquity of
> compiler implementation, probably ought to just be formalized in at
> least the serialization spec by now, if not the JLS itself, but that's
> really a tangential topic).
> Also worth noting is that the outer class instance lives in a field
> called "this$0".
> Anyway because this has always "just worked", I think that the
> definition of "significant [change]" used later on in your proposal
> should probably be changed to removing the "order" (and even "number")
> of captured arguments; the former is handled as above, and the latter
> works predictably by simply extrapolating the serialization spec rules
> about adding/removing fields to captured variables.  This is the basis
> of my earlier gripes about only using capture order (i.e. an array,
> essentially) for captures instead of names (i.e. a map like
> serialization does).
> More upcoming...
> --
> - DML


More information about the lambda-spec-experts mailing list