Java Lambdas : How it works in JVM & is it OOP? [c

2020-02-20 07:05发布

问题:

Closed. This question needs to be more focused. It is not currently accepting answers.

Want to improve this question? Update the question so it focuses on one problem only by editing this post.

Closed 4 years ago.

For example in the case of an anonymous inner class, an (anonymous) object reference is passed and methods of that object are executed.

Lambdas are code blocks which will be executed when needed.

What happens in the JVM when lambdas are encountered? Where does the JVM store the code blocks related to lambdas (Heap : Young, Old or Permanent Generation)?

I tried searching, and I got the syntax for using lambdas but was not able to understand what is happening inside JVM, as in JAVA everything is object-based.

  1. So in context of OOP how do lambdas work?

  2. Do lambdas violate OOP concepts?

  3. Is Lambda good for the garbage collector as no objects are created hence no worry about memory issues and clearing memory?

回答1:

I wouldn't waste my time thinking whether the lambda expressions are a violation of OO principles. Its goal is to increase the power of a language and not to write an OO code, I don't see how lambdas can violate encapsulation, inheritance or polymorphism.

This article explains how Java handles lambda expressions:

What’s interesting about Lambda expressions is that from the JVM’s perspective they’re completely invisible. It has no notion of what an anonymous function or a Lambda expression is. It only knows bytecode which is a strict OO specification. It’s up to the makers of the language and its compiler to work within these constraints to create newer, more advanced language elements.

Considering the following code:

List names = Arrays.asList("1", "2", "3");
Stream lengths = names.stream().map(name -> name.length());

... It begins quite simply by loading the names var and invokes its .stream() method, but then it does something quite elegant. Instead of creating a new object that will wrap the Lambda function, it uses the new invokeDynamic instruction which was added in Java 7 to dynamically link this call site to the actual Lambda function.

aload_1 //load the names var

// call its stream() func
invokeinterface java/util/List.stream:()Ljava/util/stream/Stream;

//invokeDynamic magic!
invokedynamic #0:apply:()Ljava/util/function/Function;

//call the map() func
invokeinterface java/util/stream/Stream.map:
(Ljava/util/function/Function;)Ljava/util/stream/Stream;

InvokeDynamic is an instruction that was added in Java 7 to make the JVM less strict, and allows dynamic languages to bind symbols at run-time, vs. doing all the linkage statically when the code is compiled by the JVM.

The Lambda code

aload_0
invokevirtual java/lang/String.length:()
invokestatic java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
areturn


回答2:

Lambda expressions don't get translated into anonymous inner classes, they use invoke dynamic that was introduced in Java 7 to execute functional methods. Check this out.

Do they violate OOP? I don't think that you should care. Lambdas make your code less verbose, easier to understand, and "easier" to parallelise. And thats what you should care about.

From Brain Goetz comment:

We don't get paid to write object-oriented programs or functional programs, we get paid to write working programs.



回答3:

  • Lambda expression is compiled using invokedynamic bytecode.
  • Lambda implementation is stored in the same class file as a special private method.
  • Whether an object is created to invoke lambda depends on the situation. In the trivial cases lambda gets translated to a constant method handle.
  • To instantiate a lambda HotSpot creates an anonymous class that implements lambda's functional interface. This class does not belong to any ClassLoader.

See more details from the specification lead of Lambda Expressions JSR.