Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java - SAM type optimization

A working document describing the state of Project Lambda mentions the so-called SAM (single abstract method) types. As far as I know the current lambda proposal doesn't affect the runtime just the compiler by making possible automatic conversion from lambda expressions to these types.

I think in ideal circumstances instances of SAM types could be internally represented by function pointers. Therefore the JVM could avoid memory allocation for these instances.

I am wondering whether the modern virtual machines are able to provide such optimization.

like image 442
Tamás Avatar asked Aug 16 '11 15:08

Tamás


2 Answers

@Tamás You should probably have a read of this mailing list post by Brian Goetz:

http://mail.openjdk.java.net/pipermail/lambda-dev/2011-August/003877.html

Basically, the lambda abstraction is currently implemented using objects. However, it has been designed to permit alternative realizations of lambdas, which would be "smaller" than instances of classes.

You can think of the situation as similar to autoboxing - ints are boxed to Integer, but have a "smaller" representation (as ints).

Currently, lambdas have to be boxed to instances of SAM types, b/c the JVM currently has no way to represent a lambda with any smaller construct. In the future, there may be a new JVM standard which includes "primitive functions" which could represent lambdas as something other than objects.

So, to answer your question, the type of optimization you propose above, may be possible, but it probably would come with post-Java 8 work on "primitive functions" rather than being an implementation-specific feature.

like image 140
kittylyst Avatar answered Sep 24 '22 07:09

kittylyst


There's nothing hard in converting single method classes to function pointers, but you are missing one thing: lambda expressions are not just functions, they are closures. The difference is that closures can capture outer variables. Consider next example in pseudo Java:

public Adder makeAdder(double startNumber) {
    return #{ int number -> number + startNumber}
}

...

int startNumber = 5; 
Adder add5 = makeAdder(startNumber);
add5.invoke(4);  // ==> 9 

In this example lambda function, produced by the call to makeAdder(), refers to the variable that was defined outside of this lambda. That is why it is called "closures" - they are "closed over" their free variables (in this case - over startNumber). To handle such situations closures must hold both pointer to a function and pointer to its environment. So, you get some data structure that has a method and at least one variable. But isn't it a definition of an object in OOP? So what's the reason to create new kind of objects if you can make it an instance of anonymous class?

Nevertheless some other optimizations on such anonymous classes may be done. Working document you pointed to mentions some of them, for example, inferring and using effectively final variables (though this is done mostly to allow lambdas on JVM in principal, not to optimize code). Produced anonymous class also may be done final, and most JVMs already have good optimizations for final vars and classes.

Other improvements may also concern references to environment - there are tons of options there.

like image 44
ffriend Avatar answered Sep 21 '22 07:09

ffriend