Because anonymous functions in Scala are historically
Serializable, In 2.12 we are opting to use a generic deserializer that calls
LambdaMetafactory.bootstrap, rather than emitting an indy instruction
per lambda within $deserializeLambda$, which has been noted as a problem in

Reduce size of $deserializeLambda$ method

At JVM language summit last week I was alerted to a flaw in
this approach: it inadvertently makes all private methods in the
lambda host class accessible by means of a forged SerializedLambda.
Thanks for the feedback, Remi and Brian!

I'm working to plug this hole, and thought I'd share the technique in case
if of interest beyond scalac:

SD-193 Lock down lambda deserialization

The body of $deserializeLambda$ is now a single invokedynamic. Its
bootstrap argument is an array of method handles to valid lambda target
methods. The generic deserializer creates a j.u.HashMap relating these
String keys of the form "$methodName $descriptor". It can then limit
deserialiazion to SerializedLambda-s targeting these methods.

This approach costs 2 bytes per serializable lambda in the constant
pool: all the entries are already there for the LambdaMetafactory
bootstrap args, we just refer to them again.

A downside is that the first lambda to be deserialized will incur a
one-time time + space cost proportional the total number of lambdas in
the host class to construct the map.

Here's the bytecode comparison between this proposal and javac:


Jason Zaugg
mlvm-dev mailing list

Reply via email to