Java8 lambda expression Deep Learning (4)--JAVA8 implementation method

Source: Internet
Author: User

The previous articles discussed functional interfaces and lambda expression syntax, invokedynamic directives, and how Groovy2 uses Indy directives. This article is based on a few previous articles and briefly describes how the JAVA8 layer implements lambda expressions.

Sample code

This article takes the following code as an example to expand the discussion:

Import Java.util.arrays;import Java.util.list;public class Lambdaimpltest {public        static void Main (string[] args) {        M1 (Arrays.aslist (args));    }        public static void M1 (List<string> List) {        List.sort ((A, B) a.length ()-b.length ());}    }

Insert invokedynamic directive

It is certainly possible to implement lambda expressions directly using anonymous classes , so that lambda expressions are just the syntax sugar of the Java compiler. But instead of doing this, JAVA8 is using a more complex (and more flexible) approach: using Indy directives. Obviously, this approach needs to be implemented by the compiler and the JVM together. The compiler inserts a indy instruction where each lambda expression appears, and also generates information such as the corresponding Constant_invokedynamic_info constant pool entry and Bootstrapmethods property in the class file. This information points the bootstrap method of this indy instruction to Lambdametafactory.metafactory (...). Method.

Inserting the Lambda$x&y method

Compile the Lambdaimpltest.java with Javac , and then use javap-v-P to decompile the. class file, and you can see that the compiler generated a lambda$m1$0 method, and moved the contents of the lambda expression to the inside:

The compiler generates methods for lambda expressions in accordance with certain rules to ensure that these methods do not have duplicate names. If you restore the bytecode to Java code, Lambdaimpltest will look like this:

public class Lambdaimpltest {public        static void Main (string[] args) {        m1 (Arrays.aslist (args));    }        public static void M1 (List<string> List) {        list.sort (/*lambda*/);    }        private static int lambda$m1$0 (string A, string b) {        return a.length ()-b.length ();    }    }

Lambdametafactory.metafactory (...) Method

When the JVM first executes to this indy instruction, it will find the corresponding bootstrap method of this instruction, then call the method and get a callsite. The following is the code for the Metafactory () method:

 public static CallSite Metafactory (Methodhandles.lookup caller,                                       String Invokedname, Methodtype Invokedtype,                                       Methodtype Sammethodtype, Methodhandle Implmethod, Methodtype Instantiatedmethodtype) throws Lambdaconversionexception {Abstractvalidatin        Glambdametafactory MF; MF = new Innerclasslambdametafactory (caller, Invokedtype, Invokedname, Sammeth                                             Odtype, Implmethod, Instantiatedmethodtype,        False, Empty_class_array, Empty_mt_array);        Mf.validatemetafactoryargs ();    return Mf.buildcallsite (); }
As you can guess from the code, the JAVA8 internally also implements the lambda expression in the same way as the inner class. and Innerclasslambdametafactory's Buildcallsite () method proves this, the Buildcallsite () method is too long, there is no code, in short, it will call a called Spininnerclass () method, it is this method that uses the bytecode tool to generate a class in memory.

Observe the classes generated by Spininnerclass ()

If we set the system property "Jdk.internal.lambda.dumpProxyClasses" When we start the JVM, the Spinnerclass () method will save the generated class to a file for easy debugging. If we run lambdaimpltest with the following command, we can see this class in the "Current directory":

Java-djdk.internal.lambda.dumpproxyclasses Lambdaimpltest
lambdaimpltest$ $Lambda $1.class
You can also use the JAVAP command to decompile the class file, the following is the anti-compilation result (I myself turned the JAVAP result into a Java file):

Final class lambdaimpltest$ $Lambda $ implements Java.util.Comparator {        private lambdaimpltest$ $Lambda $ () {    } public    int Compare (object A, object B) {        return lambdaimpltest.lambda$m1$0: ((String) A, (string) b);}    }
It can be seen that this inner class implements the comparator interface, and the Compare () method simply calls the Lambda$m1$0 () method. Continuing the analysis of the Buildcallsite () method, the JVM then instantiates an instance of the inner class and then creates a constantcallsite whose target methodhandle points to the Compare () method of the inner class instance.

The word description is difficult to understand, I drew a picture below:


Summarize

The Java internal implementation of the simplest lambda expression is analyzed above, which can be slightly more complicated if the lambda expression captures external parameters. But the conclusion remains the same: The JAVA8 is also implemented in the form of an inner class to implement lambda expressions.


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.