You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Exception in thread "main" java.lang.AbstractMethodError: Receiver class C$$Lambda$569/0x0000000800346c40 does not define or inherit an implementation of the resolved method 'abstract java.lang.Object apply(java.lang.Object)' of interface F1.
at Test$.applyF1$1(lambda-serialization.scala:53)
at Test$.$anonfun$allRealLambdasRoundTrip$2(lambda-serialization.scala:54)
at scala.collection.immutable.List.map(List.scala:246)
notes
To suppose lambda deserialiation, we add a synthetic $deserializeLambda$ method to each class that hosts lambda implementation methods. The JDK routes deserialization through this method. It checks that the request actually targets a method that backs a lambda (and not some random, maybe private method), by checking in a statically contructed map of all impl methods. If so, the lambda metatafactory is invoked. The metafactory invokation lives, generically, in scala.runtime.LambdaDeserializer. It does not correctly replicate the invokedynamic call at the lambda capture site as it does not include bridges.
LambdaDeserializer itself is a workaround for a problem we hit when we directly replicated the Java's strategy of simply having an invoke-dynamic-call per-lamnbda in the $deserializeLambda$. Because Scala lambdas are serializable by default, and lambda use is widespread, this method got very large, especially in DSL-like code. The large method was a problem in that it could be get too large to JIT or even too large to fit in a single method.
Maybe we can switch to a hybrid strategy where bridged lambdas have direct invokedynamic calls and scala.FunctionN cojntinue to use LambdaDeserializer. This will be cross-compatible with newly compiled user-code and the exising versions of scala.runtime.
The text was updated successfully, but these errors were encountered:
reproduction steps
using Scala 2.13.6
problem
notes
To suppose lambda deserialiation, we add a synthetic
$deserializeLambda$
method to each class that hosts lambda implementation methods. The JDK routes deserialization through this method. It checks that the request actually targets a method that backs a lambda (and not some random, maybe private method), by checking in a statically contructed map of all impl methods. If so, the lambda metatafactory is invoked. The metafactory invokation lives, generically, inscala.runtime.LambdaDeserializer
. It does not correctly replicate theinvokedynamic
call at the lambda capture site as it does not include bridges.LambdaDeserializer
itself is a workaround for a problem we hit when we directly replicated the Java's strategy of simply having an invoke-dynamic-call per-lamnbda in the$deserializeLambda$
. Because Scala lambdas are serializable by default, and lambda use is widespread, this method got very large, especially in DSL-like code. The large method was a problem in that it could be get too large to JIT or even too large to fit in a single method.Maybe we can switch to a hybrid strategy where bridged lambdas have direct invokedynamic calls and
scala.FunctionN
cojntinue to useLambdaDeserializer
. This will be cross-compatible with newly compiled user-code and the exising versions ofscala.runtime.
The text was updated successfully, but these errors were encountered: