Why Kotlin Lambda functional interfaces are not implementing Serializable?

For instance:

lateinit var l0 : () -> (Int)
lateinit var l1 : (Int) -> (Int)
lateinit var l2 : (Int, Int) -> (Int)

Function0, Function1, Function2 do not implement Serializable.

The only way to do this would be to use a custom defined functional interface:

public interface SerializableConsumer<T> extends Serializable
    void consume(T arg);

And then:

doSomething(SerializableConsumer { arg ->

This would be useful in Android development, since you could pass this lambda to a Fragment or Activity, using an Intent or Bundle.

The Serializable could be thought of as a marker interface for the author to opt-in their thing as serializable. If all lambda’s were serializable by default, how would you say that your lambda isn’t serializable?

Assuming all lambda’s should be considered serializable (or serializable by default) is a broad assumption

EDIT: There’s some really interesting discussion on an old Java mailing list on why Java decided to go with defaulting to non-serializable and using a marker interface. I’ll link it here if I find it again.

1 Like

Your reasoning is fair enough.

I do understand though, that simple constant lambda literals feel like primitive values that should be serializable by nature:

var f = { i: Int -> i + 1 }

1 Like

Is a great idea unless you have external dependencies in your function, i.e. external variables.
All those dependencies have to be serialized and deserialized, too or you require the receiver to know them.

The other point is, it is more complex, converting a function to a textual description and back is harder because of the tree structure, it requires some kind of parser and even some kind of semantic checker to verify correctness.

The question: why not send the Java File containing the class of interest as String directly to another endpoint and compile & evaluate it there by the Kotlin compiler and the JVM, respectively.

I quite like this kind of idea as I’m still not satisfied with JSON.

1 Like

because that way you can do remote code execution.
double-edged sword.

Eh, kinda. The class has to be on the other machine already, and so the code must exist there. Therefore, you can’t just serialize a random piece of code and send it to a Google API for example. The only thing that actually gets serialized is the class name.

1 Like

This isn’t always true–it can be done but the server has to load the class.

Java supports loading classes from network locations. One example can be found with Java RMI but you could always load a class form any URI. The RMI trial shows an example that is pretty close to what OP is wanting, a serializable task being sent/saved and run somewhere else.

Oh but wait, would it automatically try to find the class without any previous configuration? cuz if so then that’s a giant security vulnerability for even simple serializers that rely on class names.

The server would have to be configured to look for classes from the network source–it doesn’t load from external sources by default (excluding jre extensions).
You also have to set up a security manager so they do force you make a decision on what to allow (I think the trial has you allow all with an empty security manager).

1 Like

Oh then nevermind lol. But getting back to the initial topic, @andob said that it’ll allow you to do remote code execution if kotlin lambda implemented serializable by default, but technically that isn’t the case cuz the crucial step of allowing that on the jvm that you are running is missing, and so basically it isn’t a security vulnearability if you make all lambdas serializable, but it is a security vulnearability if you have looking for classes enabled by default from an open network api.